file_exists () слишком медленно в PHP. Кто-нибудь может предложить более быструю альтернативу? - PullRequest
33 голосов
/ 10 ноября 2009

При отображении изображений на нашем веб-сайте мы проверяем, существует ли файл, при вызове file_exists(). Мы возвращаемся к фиктивному изображению, если файл отсутствует.

Однако профилирование показало, что это самая медленная часть генерации наших страниц, когда file_exists() занимает до 1/2 мс на файл. Мы тестируем только 40 или около того файлов, но это все равно увеличивает 20 мс на время загрузки страницы.

Кто-нибудь может предложить способ сделать это быстрее? Есть ли лучший способ проверки, если файл присутствует? Если я построю какой-нибудь кеш, как мне его синхронизировать.

Ответы [ 19 ]

25 голосов
/ 10 ноября 2009

file_exists() должна быть очень недорогой операцией. Также обратите внимание, что file_exists создает собственный кэш, чтобы повысить производительность.

См .: http://php.net/manual/en/function.file-exists.php

20 голосов
/ 10 ноября 2009

Используйте абсолютные пути! В зависимости от настроек include_path PHP проверяет все (!) Эти каталоги, если вы проверяете относительные пути к файлам! Вы можете временно отключить include_path перед проверкой существования.

realpath() делает то же самое, но я не знаю, быстрее ли это.

Но доступ к файлам всегда очень медленный. Доступ к жесткому диску IS медленнее, чем вычисление чего-либо в процессоре, обычно.

17 голосов
/ 01 января 2014

Самый быстрый способ проверить наличие локального файла: stream_resolve_include_path () :

if (false !== stream_resolve_include_path($s3url)) { 
  //do stuff 
}

Результаты производительности stream_resolve_include_path () против file_exists () :

Test name       Repeats         Result          Performance     
stream_resolve  10000           0.051710 sec    +0.00%
file_exists     10000           0.067452 sec    -30.44%

В тесте использованы абсолютные пути. Источник теста здесь . Версия PHP:

PHP 5.4.23-1 ~ dotdeb.1 (cli) (сборка: 13.12.2013 21:53:21)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2013 Zend Technologies

11 голосов
/ 10 ноября 2009

Мы возвращаемся к фиктивному изображению, если файл отсутствует

Если вы просто хотите вернуться к этому фиктивному изображению, возможно, вы захотите разрешить клиенту договориться с сервером посредством перенаправления (к фиктивному изображению) файла-не-найдено.

Таким образом, у вас будут небольшие издержки перенаправления и незаметная задержка на стороне клиента. По крайней мере, вы избавитесь от «дорогого» (я знаю, что это не так) звонка на file_exists.

Просто мысль.

5 голосов
/ 25 августа 2016

Тесты с PHP 5.6:

Существующий файл:

0.0012969970 : stream_resolve_include_path + include  
0.0013520717 : file_exists + include  
0.0013728141 : @include  

Неверный файл:

0.0000281333 : file_exists + include  
0.0000319480 : stream_resolve_include_path + include  
0.0001471042 : @include  

Неверная папка:

0.0000281333 : file_exists + include  
0.0000360012 : stream_resolve_include_path + include  
0.0001239776 : @include  

Код:

// microtime(true) is less accurate.
function microtime_as_num($microtime){
  $time = array_sum(explode(' ', $microtime));
  return $time;
}

function test_error_suppression_include ($file) {
  $x = 0;
  $x = @include($file);
  return $x;
}

function test_file_exists_include($file) {
  $x = 0;
  $x = file_exists($file);
  if ($x === true) {
    include $file;
  }
  return $x;
}

function test_stream_resolve_include_path_include($file) {
  $x = 0;
  $x = stream_resolve_include_path($file);
  if ($x !== false) {
    include $file;
  }
  return $x;
}

function run_test($file, $test_name) {
  echo $test_name . ":\n";
  echo str_repeat('=',strlen($test_name) + 1) . "\n";

  $results = array();
  $dec = 10000000000; // digit precision as a multiplier

  $i = 0;
  $j = 0;
  $time_start = 0;
  $time_end = 0;
  $x = -1;
  $time = 0;

  $time_start = microtime();
  $x= test_error_suppression_include($file);
  $time_end = microtime();
  $time = microtime_as_num($time_end) - microtime_as_num($time_start);

  $results[$time*$dec] = '@include';

  $i = 0;
  $j = 0;
  $time_start = 0;
  $time_end = 0;
  $x = -1;
  $time = 0;

  $time_start = microtime();
  $x= test_stream_resolve_include_path_include($file);
  $time_end = microtime();
  $time = microtime_as_num($time_end) - microtime_as_num($time_start);

  $results[$time * $dec] = 'stream_resolve_include_path + include';

  $i = 0;
  $j = 0;
  $time_start = 0;
  $time_end = 0;
  $x = -1;
  $time = 0;

  $time_start = microtime();
  $x= test_file_exists_include($file);
  $time_end = microtime();
  $time = microtime_as_num($time_end) - microtime_as_num($time_start);

  $results[$time * $dec ] = 'file_exists + include';

  ksort($results, SORT_NUMERIC);

  foreach($results as $seconds => $test) {
    echo number_format($seconds/$dec,10) . ' : ' . $test . "\n";
  }
  echo "\n\n";
}

run_test($argv[1],$argv[2]);

Командная строка Выполнение:

php test.php '/path/to/existing_but_empty_file.php' 'Existing File'  
php test.php '/path/to/non_existing_file.php' 'Invalid File'  
php test.php '/path/invalid/non_existing_file.php' 'Invalid Folder'  
3 голосов
/ 10 ноября 2009

Создание процедуры хеширования для разделения файлов на несколько подкаталогов.

filename.jpg -> 012345 -> /01/23/45.jpg

Кроме того, вы можете использовать mod_rewrite для возврата изображения-заполнителя для запросов в каталог изображений, который 404.

3 голосов
/ 10 ноября 2009

file_exists() автоматически кэшируется PHP. Я не думаю, что вы найдете более быструю функцию в PHP для проверки существования файла.

См. эту тему .

2 голосов
/ 26 июля 2010

Я точно не знаю, что вы хотите сделать, но вы можете просто позволить клиенту справиться с этим .

2 голосов
/ 10 ноября 2009

Если вы проверяете только на наличие files, используйте is_file(). file_exists() проверяет существующий каталог ИЛИ файла, поэтому is_file() может быть немного быстрее.

1 голос
/ 10 ноября 2009

Они все в одном каталоге? Если это так, то может стоить получить список файлов и сохранить их в хэше и сравнить с ними, а не со всеми поисками file_exists.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...