Производительность PHP file_get_contents() по сравнению с readfile() и cat

#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 стал таким же медленным, как readfile

3. Вау, это очень интересно. Это многое объясняет

Ответ №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.