#php #performance #io #cat
#php #Производительность #io #cat
Вопрос:
Я провожу некоторый сравнительный анализ с функциями чтения файлов PHP просто для моих общих знаний. Итак, я протестировал три разных способа чтения всего содержимого файла, которые, как я думал, будут очень быстрыми.
- file_get_contents() хорошо известна своей очень высокой производительностью
- известно, что readfile() является очень хорошей альтернативой file_get_contents (), когда дело доходит до вывода данных непосредственно в
stdout
- exec(‘cat filename’) одна очень удобная и быстрая команда UNIX
Итак, вот мой тестовый код, обратите внимание, что я включил систему кэширования PHP для readfile()
, чтобы избежать прямого вывода, который полностью фальсифицировал бы результаты.
<?php
/* Using a quick PNG file to benchmark with a big file */
/* file_get_contents() benchmark */
$start = microtime(true);
$foo = file_get_contents("bla.png");
$end = microtime(true) - $start;
echo "file_get_contents() time: " . $end . "sn";
/* readfile() benchmark */
ob_start();
$start = microtime(true);
readfile('bla.png');
$end = microtime(true) - $start;
ob_end_clean();
echo "readfile() time: " . $end . "sn";
/* exec('cat') benchmark */
$start = microtime(true);
$bar = exec('cat bla.png');
$end = microtime(true) - $start;
echo "exec('cat filename') time: " . $end . "sn";
?>
Я запускал этот код несколько раз, чтобы подтвердить показанные результаты, и каждый раз у меня был один и тот же порядок. Вот пример одного из них:
$ php test.php
file_get_contents() time: 0.0006861686706543s
readfile() time: 0.00085091590881348s
exec('cat filename') time: 0.0048539638519287s
Как вы можете видеть, file_get_contents()
сначала появляется, затем прибывает readfile()
и, наконец cat
Что касается cat
даже несмотря на то, что это UNIX
команда (такая быстрая и все такое :)) Я понимаю, что вызов отдельного двоичного файла может привести к относительно высокому результату. Но мне трудно понять, почему это file_get_contents()
быстрее, чем readfile()
? В конце концов, это примерно в 1,3 раза медленнее.
Обе функции встроены и, следовательно, довольно хорошо оптимизированы, и поскольку я включил кэш, readfile() не «пытается» выводить данные в stdout
, но, как и file_get_contents(), помещает данные в оперативную память.
Я ищу здесь техническое объяснение низкого уровня, чтобы понять плюсы и минусы file_get_contents()
и readfile()
помимо того факта, что один предназначен для записи непосредственно в стандартный вывод, тогда как другой выполняет распределение памяти внутри ОЗУ.
Заранее спасибо.
Ответ №1:
file_get_contents
загружает только данные из файла в память, в то время как readfile
и cat
также выводят данные на экран, поэтому они просто выполняют больше операций.
Если вы хотите сравнить file_get_contents
с другими, добавьте echo
перед этим
Кроме того, вы не освобождаете память, выделенную для $ foo . Есть вероятность, что если вы переместите file_get_contents в качестве последнего теста, вы получите другой результат.
Кроме того, вы используете буферизацию вывода, которая также вызывает некоторые различия — просто попробуйте добавить остальные функции в код буферизации вывода, чтобы устранить любые различия.
При сравнении различных функций остальная часть кода должна быть одинаковой, в противном случае вы открыты для всех видов влияний.
Комментарии:
1. Я изменил порядок file_get_contents() и readfile (), и я все еще получаю те же результаты. Но я думаю, вы были правы со своей первой гипотезой, потому что это единственное объяснение, которое я могу понять.
2. @ValentinMercier Я изменил тест на:
ob_start(); $start = microtime(true); echo file_get_contents("$file"); $end = microtime(true) - $start; ob_end_clean();
и file_get_contents стал таким же медленным, как readfile3. Вау, это очень интересно. Это многое объясняет
Ответ №2:
file_get_contents
функция обычно считается более быстрой, чем функция readfile, когда дело доходит до кэширования, поскольку она позволяет сохранять данные в кэше памяти, тогда как readfile записывает данные непосредственно в выходной буфер, минуя кэш памяти.
Это позволяет легко манипулировать содержимым файла и кэшировать его в памяти, что может привести к более быстрому времени доступа по сравнению с функцией readfile, которая считывает файл по одному фрагменту за раз и выводит содержимое непосредственно в браузер. file_get_contents
может использовать преимущества системы кэширования памяти PHP (opcache).
Если в некоторых случаях вы не можете использовать file_get_contents
, вы можете использовать механизм буферизации вывода в PHP для кэширования содержимого файла перед отправкой его клиенту. Это позволит вам использовать систему кэширования памяти PHP с функцией readfile. Вы можете сделать это, запустив выходной буфер с помощью ob_start
функции перед вызовом readfile, а затем очистив буфер с помощью ob_end_flush
функции. Таким образом, содержимое файла будет сохранено в выходном буфере, который является частью системы кэширования памяти PHP.