PHP:file_exists vs stream_resolve_include_path - 啥表现更好?

Posted

技术标签:

【中文标题】PHP:file_exists vs stream_resolve_include_path - 啥表现更好?【英文标题】:PHP: file_exists vs stream_resolve_include_path - What Performs Better?PHP:file_exists vs stream_resolve_include_path - 什么表现更好? 【发布时间】:2013-10-19 23:25:21 【问题描述】:

似乎最近 php 开发人员对在检查文件是否存在时使用 file_exists() 或 stream_resolve_include_path() 是否更好(包括它们、缓存系统等)。

这让我想知道是否有人做过任何基准测试,在页面加载时间、服务器性能和内存使用方面哪个是更好的选择。

我在 SO 找不到任何解决这个问题的东西,所以认为是时候让我们这样做了。

【问题讨论】:

【参考方案1】:

我做了一个小基准测试,但在结果之前,让我们看看这些函数是如何工作的。您可以阅读 PHP 源代码here。有一个french version of this answer,本周早些时候写的,好时机;)。

我也会讨论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() 需要支付一点费用,这解释了数字略高的原因。

【讨论】:

以上是关于PHP:file_exists vs stream_resolve_include_path - 啥表现更好?的主要内容,如果未能解决你的问题,请参考以下文章

PHP:readfile-手册

PHP file_exists() 在某些文件上返回 false

PHP - file_exists 需要很长时间

php中file_exists的CPU负载

file_exists() 的 PHP 不区分大小写版本

PHP 中的 file_exists 未按预期工作