PHP:file_exists vs stream_resolve_include_path - 什么表现更好?

Abe*_*ela 5 php file-exists

似乎最近有很多人想知道php开发人员在检查文件是否存在时是否更好地使用file_exists()stream_resolve_include_path()(是否包含它们,缓存系统)等).

它让我想知道是否有人在那里做了任何基准测试,对于页面加载时间,服务器性能和内存使用情况,哪一个是更好的选择.

我在SO处找不到任何解决这个问题的东西,所以我们觉得是时候这样做了.

Tig*_*222 13

我做了一些基准测试,但在结果之前,让我们看看这些功能是如何工作的.您可以在此处阅读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
}
Run Code Online (Sandbox Code Playgroud)

而过程的伪代码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)
}
Run Code Online (Sandbox Code Playgroud)

从这里开始,如果没有基准测试的数字结果,您可以看到一个函数在资源中是如何昂贵的.


基准代码:

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]
    );

}
Run Code Online (Sandbox Code Playgroud)

让我们用existsante文件(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
Run Code Online (Sandbox Code Playgroud)

结果不言自明;)


基准测试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>';
Run Code Online (Sandbox Code Playgroud)

结果:

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

拨打电话需要一点费用$funct(),这可以解释稍高的数字.