PHP: file_exists vs stream_resolve_include_path – Что лучше?

Похоже, что в последнее время разработчики php довольно часто задаются вопросом о том, лучше ли использовать file_exists () или stream_resolve_include_path () при проверке наличия или отсутствия файла (будь то включение их, системы кеширования , и т.д).

Мне стало интересно, кто-нибудь из них проведет любое тестовое тестирование, какой из них является лучшим вариантом для загрузки страницы, производительности сервера и использования памяти.

Я не мог найти что-либо здесь, в SO, чтобы решить эту проблему, поэтому подумал, что пришло время для этого.

Solutions Collecting From Web of "PHP: file_exists vs stream_resolve_include_path – Что лучше?"

Я сделал небольшой ориентир, но до результатов посмотрим, как работают эти функции. Здесь вы можете прочитать исходный код PHP. Существует французская версия этого ответа , написанная ранее на этой неделе, хорошее время;).

Я также расскажу о is_file() , так как он определен в одну и ту же основную функцию в источнике. По основной функции я говорю источник C, не доступный из языка PHP в ваши скрипты.

Насколько я понимаю, file_exists() и is_file() являются php_stat() основной функции php_stat() . Это очень упрощенный псевдокод процесса:

 function php_stat($file) { 'file_exists' ↳ virtual_file_ex($file) ↳ virtual_access($file) 'Windows' ↳ tsrm_win32_access($file) ↳ return access($file) 'Other systems' ↳ return access($file) 'is_file' ↳ return $file.st_mode == S_IFREG } 

И псевдокод процесса stream_resolve_include_path() :

 function stream_resolve_include_path($file) { zend_resolve_path($file) ↳ php_resolve_path_for_zend($file) ↳ php_resolve_path($file) ↳ tsrm_realpath($file) ↳ return estrdup($file) } 

Отсюда, без количественного результата теста, вы можете увидеть, как одна функция стоит дорого в ресурсе.


Код для эталона:

 function bench_file($file) { $res = array(); $max = 1000000; // is_file() $res[] = microtime(1); for ( $i = 0; $i < $max; ++$i ) { if ( is_file($file) ) { // } } $res[] = microtime(1); clearstatcache(); // file_exists() $res[] = microtime(1); for ( $i = 0; $i < $max; ++$i ) { if ( file_exists($file) ) { // } } $res[] = microtime(1); clearstatcache(); // stream_resolve_include_path() $res[] = microtime(1); for ( $i = 0; $i < $max; ++$i ) { if ( stream_resolve_include_path($file) !== false ) { // } } $res[] = microtime(1); printf( 'is_file = %f, file_exists = %f, stream_resolve_include_path = %f', $res[1] - $res[0], $res[3] - $res[2], $res[5] - $res[4] ); } 

Давайте проверим с файлом existante (1) и непрочным (2):

 1 : is_file = 0.218582, file_exists = 0.742195, stream_resolve_include_path = 1.626521 2 : is_file = 0.458983, file_exists = 0.644638, stream_resolve_include_path = 5.623289 

Результаты говорят сами за себя;)


Benchmark v2 – просто более простой способ добавить новые функции для тестирования.

 function micro($func, $file) { $max = 1000000; $start = microtime(1); for ( $i = 0; $i < $max; ++$i ) { if ( $func($file) ) { // } } $end = microtime(1); clearstatcache(); return $end - $start; } function bench_file($file) { $res = array( 'is_file' => micro('is_file', $file), 'file_exists' => micro('file_exists', $file), 'stream_resolve_include_path' => micro('stream_resolve_include_path', $file) ); $ret = ''; foreach ( $res as $key => $value ) { $ret .= sprintf('%s = %f, ', $key, $value); } return trim($ret, ', '); } echo '<pre>', bench_file('file-ok'), "\n", bench_file('file-ko'), '</pre>'; 

Результаты:

 is_file = 0.295752, file_exists = 0.852082, stream_resolve_include_path = 1.759607 is_file = 0.527770, file_exists = 0.724793, stream_resolve_include_path = 5.916151 

Существует немного затрат на вызов $funct() , это объясняет несколько более высокие цифры.