Мне было интересно, что произойдет, если несколько скриптов совместно используют один и тот же файл. Я загрузил тест на удаленный сервер, где они используют жесткий диск для хранения данных. Всего было проведено 7 тестов, но семейство из 6 совместимо.
У меня есть 7 файлов разного размера, которые я загрузил на сервер и тест. Это цикл, который читает и записывает данные из файлов.
В цикле задержка составляет 50 микросекунд. Цикл повторяется 50x.
Я измеряю время, необходимое для выполнения каждого круга.
Различия в тестах (T):
Использование file_get_contents / file_put_contents
T2 - ИСТОЧНИК <> TARGET - считывает данные из исходного файла,записывает данные в другой (новый) файл
T3 - SOURCE = TARGET - 1. копирует данные из исходного файла в целевой;2. читает исходные данные -> записывает данные;3. пункт 3 повторяется: т.е. я читаю данные, которые я написал. Этот тест использует тот же файл для записи данных.
T4 - SOURCE = TARGET - я повторил тот же тест, что и в T3, получая закороченные времена.
Использование fopen, flock, fread, flock, fclose, fopen, flock, fopen, fwrite, fflush , fclock, fclose ... Это сложный код, но здесь я протестировалfflush. Я также использую clearstatcache, stat и touch и clearstatcache, размер файла. Проверить правильность. Тесты T5 - T7 были менее надежными, чем T2-T4, потому что иногда операция записи не выполнялась. Я проверил размер файла и, когда он был неправильным, я скопировал (восстановил) файл обратно из исходного файла.
T5 : (fflush) SOURCE = TARGET
T6 : (fflush) SOURCE <> TARGET
T7 : (fflush) SOURCE <> TARGET + Я удалил задержку в 50 микросекунд из цикла (кажетсянапример, достоверность / надежность хуже при наличии задержки).
Я сделал 4 запроса от 4 разных браузеров - поэтому в каждом тесте было 4 набора данных (всего 7 * 50 * 4 значений).
Теперь я собрал все данные, создал таблицы и диаграммы. Это одна из многих диаграмм, показывающая минимальные и максимальные значения среднего значения.
T4 желтого цвета и T3 зеленого обеспечивает очень малое время, поэтому они подозрительны. Например, средние значения времени T4: 0,001
0.001 0.002 0.003 0.002 0.004 0.003 0.004 0.001 0.004 0.001 0.004 0.001 0.004
и времена T3:
0.002 0.003 0.001 0.001 0.003 0.003 0.006 0.007 0.002 0.003 0.004 0.004 0.019 0.019
Значения T2 кажутся нормальными, но это можно объяснить тем фактом, что это былочтение из другого файла, чем было записано.
T5-T7 просто показывает нормальное время, как и ожидалось - чем больше файл, тем больше время, необходимое для обработки. Довольно медленный, как и ожидалось, от жесткого диска и 4-х сценариев, запущенных одновременно.
Итак, мой вопрос здесь:
Означают ли результаты T3-T4, что file_read_contents и file_put_contentsне являются надежными для этого типа работы? Мне кажется, что они просто не читают данные из файла, но копируются из буфера, что означает, что старые данные сохранены, а не текущие данные были изменены с помощью concurentскрипт. Я хотел бы получить больше информации. Я потратил много времени на поиск ответов, но не нашел четкого ответа. Я сделал это тесты, потому что мне нужны доказательства. Вы хотите использовать мои сценарии, но я не уверен, могу ли я вставить здесь 6 сценариев? Теперь я добавлю только тест fflush № 7, который наиболее полезен.
<?PHP
clearstatcache();
$_DEBUG_ = false;
echo "Lock and flush tester.".time()."<br>";
die;
while ( time()<1570787996 )
{
usleep(500);
}
function test($n, $p, $_DEBUG_){
$sname = "$n"; // source
$tname = "$n.txt";// target
echo "<h4>$n at ".time()."</h4>";
for ($i = 0; $i<50; $i++ ){
$start = microtime(true);
clearstatcache(); // needed for filesize and touch
$st = stat("$sname");
$original_size = $st['size'];
if ( $_DEBUG_ )
echo "; 1) prevAccess by ".$st['mtime']." fsize ".$st['size']."; ";
$fsize = filesize($sname);
if ( $original_size <> $fsize )
die("; fsize total FAILTURE; ");
if ($fsize === 0)
echo "! <b>The fsize is 0</b>: stat(): ".$st['size']." ;";
else
{
// READ OPERATION AND LOCK FOR SHARE
$locked = false;
for ($c = 0; !$locked; $c++):
if ( $c > 400)
break;
$fp = fopen($sname, "r");
$locked = flock($fp, LOCK_SH);
if ($locked)
break;
else
{
echo "failed to get LOCK_SH;<br>";
usleep(5000);
}
endfor;
$s = fread($fp, $fsize );
$success = flock($fp, LOCK_UN);
if ( $success === false )
die("; r flock release failed; ");
$success = fclose($fp);
if ( $success === false )
die("; fclose failed; ");
// 10 - data loaded , $p - browser
if ( $success )
{
$result = touch("$sname",strlen($s),$p);
if ( $_DEBUG_ )
echo "; TOUCH: $result;";
}
else
die("fclose FAIL.");
if ( strlen($s)<60 )
echo "*$s LENGTH:".strlen($s)."<br>";
}
clearstatcache();
$st = stat("$tname");
if ( $_DEBUG_ )
echo "; 2) prevAccess by ".$st['mtime']." fsize is ".$fsize."; ";
// WRITE OPERATION WITH LOC_EX
$fp = fopen($tname, "w");
$locked = false;
$locked = flock($fp, LOCK_EX);
if ( $locked ) { // acquire an exclusive lock
$success = fwrite($fp, $s);
if ( $success === false)
echo "; w FAILED;";
else
if ( $_DEBUG_ )
echo " $success B written; ";
$success = fflush($fp);// flush output before releasing the lock
if ( $success === false )
echo "; flush FAILED; ";
$success = flock($fp, LOCK_UN); // release the lock
if ( $success === false )
echo "; release FAILED; ";
$success = fclose($fp);
if ( $success === false )
echo "; fclose FAILED; ";
clearstatcache(); // needed for filesize and touch
$fsize = filesize($tname);
if ($original_size>$fsize)
{
echo "; <b>WRITE FAILED, restoring</b>;";
$original_fname = "$n";
$result = copy($original_fname, $tname);
if ($result == false )
die(" <b>TOTAL FAILTURE: copy failed.</b>");
else
echo " <b>RESTORED</b>;";
}
else
{
if ($fsize === 0)
echo "! THE FILE WAS NOT WRITTEN: data length: ".strlen($s)." fsize: $fsize RESOURCE: $fp<br>";
if ( $success )
touch("$tname",$fsize,$p);
}
} else {
echo "Couldn't get the lock!";
}
$time_elapsed_secs = microtime(true) - $start;
if ( $time_elapsed_secs === 0 )
echo " FAILED ";
echo "time: $time_elapsed_secs s<br>";
}
}
switch ( $_SERVER['HTTP_USER_AGENT'] ):
// FF 1:
case "Mozilla/5.0 (Windows NT 5.1; rv:49.0) Gecko/20100101 Firefox/49.0":
$p = 1; break;
// Chrome:
case "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36":
$p = 2; break;
// OPERA:
case "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36 OPR/36.0.2130.80":
$p = 3; break;
endswitch;
copy("523","523.txt");
copy("948","948.txt");
copy("1371","1371.txt");
copy("1913","1913.txt");
copy("2701","2701.txt");
copy("4495","4495.txt");
copy("6758","6758.txt");
test("523",$p,$_DEBUG_);
test("948",$p,$_DEBUG_);
test("1371",$p,$_DEBUG_);
test("1913",$p,$_DEBUG_);
test("2701",$p,$_DEBUG_);
test("4495",$p,$_DEBUG_);
test("6758",$p,$_DEBUG_);
die;
echo "php: " . phpversion();
?>
<?PHP echo "php: " . phpinfo();
?>
Вы можете включить опцию $ DEBUG для мониторинга каждого процесса. Примечание. Сенсорный экран может работать не всегда корректно.
Примечание. Это не запрос на проверку, это просто запрос на проверку.
![file_put_contents vs fflush](https://i.stack.imgur.com/fDp7V.png)
Также: пожалуйста, не смущайтесь желтой кривой цвета. Есть два желтых цвета. Желтый T4 почти не виден на диаграмме, потому что он имеет очень низкие значения.