2012-01-01 50 views
29

1]哪個功能更快?
2]有什麼區別?
readdir vs scandir

Differences

1]的readdir返回目錄下一個條目的名稱。 Scandir從目錄中返回一組文件和目錄。

2] readdir必須打開資源句柄,直到讀取所有條目。 scandir,可能會創建一個包含所有條目的數組並關閉資源句柄?

+0

可能的重複[使用PHP的數組目錄](http://stackoverflow.com/questions/2120287/directory-to-array-with-php) – salathe 2012-01-01 11:35:28

回答

12

剛開結果(什麼也不做),readdir的是最低速度快:

<?php 

$count = 10000; 

$dir = '/home/brati'; 

$startScan = microtime(true); 
for ($i=0;$i<$count;$i++) { 
    $array = scandir($dir); 
} 
$endScan = microtime(true); 


$startRead = microtime(true); 
for ($i=0;$i<$count;$i++) { 
    $handle = opendir($dir); 
    while (false !== ($entry = readdir($handle))) { 
     // We do not know what to do 
    } 
} 
$endRead = microtime(true); 

echo "scandir: " . ($endScan-$startScan) . "\n"; 
echo "readdir: " . ($endRead-$startRead) . "\n"; 

給出:

== RUN 1 == 
scandir: 5.3707950115204 
readdir: 5.006147146225 

== RUN 2 == 
scandir: 5.4619920253754 
readdir: 4.9940950870514 

== RUN 3 == 
scandir: 5.5265231132507 
readdir: 5.1714680194855 

然後,當然這取決於你打算做什麼。如果你必須用scandir()編寫另一個循環,它會變慢。

15

這真的取決於您對數據所做的事情。

如果您要逐條輸入,則應該使用readdir,如果您確實需要列出內存條目,則應該使用scandir

無論如何將信息複製到內存中無論如何你都要逐條使用它。在這種情況下,懶惰評估絕對是最好的選擇。

我會想象,scandir只是一個圍繞readdir調用相同的東西的包裝,因此會更慢。

2

做了一些更多的時間比較讀取整個目錄樹,用大量的文件和目錄:

  • 通話文件類型()==「目錄」明顯快於is_dir()調用

  • 執行opendir/readdir的調用比RecursiveDirectoryIterator

  • 建築快得多第一或線性使用遞歸調用深度的目錄樹沒什麼區別

其中在Windows一致的結果,進行本地SSD,本地USB和網絡驅動器的上述試驗。在網絡驅動器上運行的速度比本地驅動器慢180倍 - 儘管千兆和其他快速的ReadyNAS設備!

每秒處理的條目數從115到最慢的代碼到網絡驅動器到65000代表最快的代碼到USB 3.0驅動器 - 當然是由於緩存。

但是,網絡驅動器的巨大差異使您想知道PHP內部會發生什麼,因爲簡單的dir命令和ls在Linux中通過相同的文件更快。

待續...

2

我已經做了一些測試。 (感謝Aufziehvogel建築)

$count = 100000; 

$dir = dirname(__FILE__); 

$startScan = microtime(true); 
for ($i=0;$i<$count;$i++) { 
    $array = scandir($dir); 
} 
$endScan = microtime(true); 

$startRead = microtime(true); 
for ($i=0;$i<$count;$i++) { 
    $handle = opendir($dir); 
    while (false !== ($entry = readdir($handle))) { 
     // We do not know what to do      
    } 
} 
$endRead = microtime(true); 

$startGlob = microtime(true); 
for ($i=0;$i<$count;$i++) { 
    $array3 = glob('*'); 
} 
$endGlob = microtime(true); 

echo "scandir: " . ($endScan-$startScan) . "\n"; 
echo "readdir: " . ($endRead-$startRead) . "\n"; 
echo "glob : " . ($endGlob-$startGlob) . "\n"; 

Linux服務器結果:

scandir: 0.82553291320801 
readdir: 0.91677618026733 
glob : 0.76309990882874 

這Reasults從4芯(8個線程)英特爾E3-1240的Cpu LINUX + Apache服務器。

但Windows服務器結果相反。的Windows + Apache服務器 - 英特爾Q8400四核心(四個線程)

的Windows Server結果:

$count = 10000; // it was on linux 100000 :) 

scandir: 0.61557507515 
readdir: 0.614650011063 
glob : 1.92112612724 

(文件夾包括13個文件,如果文件是增加,結果可能會有所不同。)

2

我知道這個問題現在可能不是現實的,但爲了追加,我已經做了一些測試(如Aufziehvogel和Sayahan),它們有一個小小的區別 - 在一個有1,000,000個小文件(幾個字節)的目錄上。

$dir = dirname(__FILE__) . '/dir'; 

$startScan = microtime(true); 
$array = scandir($dir); 
for ($i = 0, $j = count($array); $i < $j; $i++) { 
    // Code 
} 
$endScan = microtime(true); 
unset($array); 

$startRead = microtime(true); 
$handle = opendir($dir); 
while (false !== ($entry = readdir($handle))) { 
    // Code 
} 
$endRead = microtime(true); 
unset($handle); 
unset($entry); 

$startDir = microtime(true); 
$files = new DirectoryIterator($dir); 
foreach ($files as $file) { 
    // Code 
} 
$endDir = microtime(true); 
unset($files); 

echo 'scandir:   ', ($endScan - $startScan), PHP_EOL; 
echo 'readdir:   ', ($endRead - $startRead), PHP_EOL; 
echo 'DirectoryIterator: ', ($endDir - $startDir), PHP_EOL; 

結果(HDD):

scandir:   1.9403479099274 
readdir:   0.79462885856628 
DirectoryIterator: 0.5853099822998 

結果(SSD):

scandir:   0.83593201637268 
readdir:   0.35835003852844 
DirectoryIterator: 0.28022909164429 

CPU:AMD A10-4600M APU用的Radeon(TM)HD圖形(4芯)
MEM:8G
PHP:5.6.29