似乎最近 php 开发人员对在检查文件是否存在时使用file_exists()或stream_resolve_include_path()是否更好(包括它们,缓存系统)有相当多的疑问, ETC)。
这让我想知道是否有人针对页面加载时间、服务器性能和内存使用情况进行了任何基准测试,以确定哪些是更好的选择。
我在 SO 找不到任何解决这个问题的东西,所以我想是时候这样做了。
似乎最近 php 开发人员对在检查文件是否存在时使用file_exists()或stream_resolve_include_path()是否更好(包括它们,缓存系统)有相当多的疑问, ETC)。
这让我想知道是否有人针对页面加载时间、服务器性能和内存使用情况进行了任何基准测试,以确定哪些是更好的选择。
我在 SO 找不到任何解决这个问题的东西,所以我想是时候这样做了。
我做了一个小基准测试,但在结果之前,让我们看看这些函数是如何工作的。您可以在此处阅读 PHP 源代码。这个答案有一个法语版本,本周早些时候写的,时机很好;)。
我也会讲is_file()
,因为它在源代码中定义为相同的核心函数。通过核心功能,我说 C 源代码,不能从 PHP 语言访问到您的脚本中。
我所理解的,file_exists()
并且is_file()
是核心功能的孩子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]
);
}
让我们用一个存在的文件 (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()
,这解释了稍微高一点的数字。