file_exists()在PHP中太慢了.有谁能建议更快的替代方案?

Rik*_*ood 34 php performance file-exists

在我们的网站上显示图像时,我们会通过调用来检查文件是否存在file_exists().如果文件丢失,我们会回到虚拟图像.

但是,分析表明,这是生成页面最慢的部分,每个文件file_exists()占用最多1/2毫秒.我们只测试40个左右的文件,但这仍然会在页面加载时间上推迟20ms.

任何人都可以建议一种方法来加快速度吗?如果文件存在,是否有更好的测试方法?如果我构建某种缓存,我应该如何保持同步.

RC.*_*RC. 27

file_exists()应该是一个非常便宜的操作.另请注意,file_exists构建自己的缓存以提高性能.

请参阅:http://php.net/manual/en/function.file-exists.php

  • 根据文档,只有在file_exists()返回true时才会发生缓存.因此,如果您碰巧检查存在的文件,该函数将每次都检查.当file_exists()返回false时,您可以为虚拟映像创建符号链接,以便后续调用将被缓存.(这可能会导致其他问题) (4认同)
  • 我想我应该接受表现很好,并保持原样.我可能会把文件拆分成更多的文件夹,因为这可能会有所帮助. (3认同)

pow*_*tac 21

使用绝对路径!根据您的include_path设置,如果您检查相关文件路径,PHP会检查所有(!)这些目录!include_path在检查存在之前,您可能会暂时取消设置.

realpath() 做同样但我不知道它是否更快.

但是文件访问I/O总是很慢.硬盘访问IS比计算在所述处理器的东西,通常是较慢的.


Ale*_*ruk 18

检查本地文件是否存在的最快方法是stream_resolve_include_path():

if (false !== stream_resolve_include_path($s3url)) { 
  //do stuff 
}
Run Code Online (Sandbox Code Playgroud)

性能结果stream_resolve_include_path() vs file_exists():

Test name       Repeats         Result          Performance     
stream_resolve  10000           0.051710 sec    +0.00%
file_exists     10000           0.067452 sec    -30.44%
Run Code Online (Sandbox Code Playgroud)

在测试中使用绝对路径.测试源在这里.PHP版本:

PHP 5.4.23-1~dadedeb.1(cli)(建于2013年12月13日21:53:21)
版权所有(c)1997-2013 PHP Group
Zend Engine v2.4.0,版权所有(c)1998-2013 Zend Technologies


jen*_*ram 11

如果文件丢失,我们会回到虚拟图像

如果您只想回到这个虚拟映像,您可能需要考虑让客户端通过在文件未找到的重定向(到虚拟映像)来与服务器协商.

这样你就会有一点重定向开销和客户端不明显的延迟.至少你会摆脱"昂贵"(我不知道)的号召file_exists.

只是一个想法.

  • +1聪明.现在我很好奇如果你通过404响应传回jpg数据会发生什么.毕竟,这是OP正在寻找的404型行为. (2认同)

Jon*_*ner 5

PHP 5.6的基准测试:

现有文件:

0.0012969970 : stream_resolve_include_path + include  
0.0013520717 : file_exists + include  
0.0013728141 : @include  
Run Code Online (Sandbox Code Playgroud)

无效的文件:

0.0000281333 : file_exists + include  
0.0000319480 : stream_resolve_include_path + include  
0.0001471042 : @include  
Run Code Online (Sandbox Code Playgroud)

无效的文件夹:

0.0000281333 : file_exists + include  
0.0000360012 : stream_resolve_include_path + include  
0.0001239776 : @include  
Run Code Online (Sandbox Code Playgroud)

码:

// 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]);
Run Code Online (Sandbox Code Playgroud)

命令行执行:

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'  
Run Code Online (Sandbox Code Playgroud)