2013-10-11 26 views
4

似乎最近有很多人對php開發人員感到疑惑,在檢查文件是否存在(是否包括它們,緩存系統等等)時,最好使用file_exists()還是stream_resolve_include_path() )。PHP:file_exists vs stream_resolve_include_path - 什麼執行更好?

它讓我想知道是否有人在那裏做了任何基準測試,哪些是更好的選擇,包括頁面加載時間,服務器性能和內存使用情況。

我在SO這裏找不到任何解決這個問題的東西,所以我們可以這麼做。

回答

12

我已經做了一點基準測試,但在結果之前,讓我們看看這些函數是如何工作的。您可以閱讀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] 
    ); 

} 

讓我們從一個existante文件(1)和一個inexistant一個(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 - just一個更簡單的方法來添加新的功能來測試。

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(),這解釋了稍高的數字。

相關問題