似乎最近有很多人對php開發人員感到疑惑,在檢查文件是否存在(是否包括它們,緩存系統等等)時,最好使用file_exists()還是stream_resolve_include_path() )。PHP:file_exists vs stream_resolve_include_path - 什麼執行更好?
它讓我想知道是否有人在那裏做了任何基準測試,哪些是更好的選擇,包括頁面加載時間,服務器性能和內存使用情況。
我在SO這裏找不到任何解決這個問題的東西,所以我們可以這麼做。
似乎最近有很多人對php開發人員感到疑惑,在檢查文件是否存在(是否包括它們,緩存系統等等)時,最好使用file_exists()還是stream_resolve_include_path() )。PHP:file_exists vs stream_resolve_include_path - 什麼執行更好?
它讓我想知道是否有人在那裏做了任何基準測試,哪些是更好的選擇,包括頁面加載時間,服務器性能和內存使用情況。
我在SO這裏找不到任何解決這個問題的東西,所以我們可以這麼做。
我已經做了一點基準測試,但在結果之前,讓我們看看這些函數是如何工作的。您可以閱讀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()
,這解釋了稍高的數字。