2012-01-01 11 views
29

1] Która z funkcji jest szybsza?
2] Jakie są różnice?
readdir vs scandir

Differences

1] readdir zwraca nazwę następnego wpisu w katalogu. Scandir zwraca z katalogu szereg plików i katalogów.

2] readdir musi mieć uchwyt zasobu otwarty, dopóki wszystkie wpisy nie zostaną przeczytane. scandir, być może tworzy tablicę wszystkich wpisów i zamyka uchwyt resouce?

+0

możliwy duplikat [Katalog do tablicy z PHP] (http://stackoverflow.com/questions/2120287/directory-to-array-with-php) – salathe

Odpowiedz

12

Wystarczy uzyskano wyniki (nie robiąc nic), readdir jest minimalna szybciej:

<?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"; 

Daje:

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

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

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

Wtedy oczywiście to zależy od tego, co zamierza zrobić. Jeśli musisz napisać kolejną pętlę za pomocą scandir(), będzie wolniej.

15

To naprawdę zależy od tego, co robisz z danymi.

Jeśli przechodzisz przez entry-by-entry, powinieneś używać readdir, jeśli rzeczywiście potrzebujesz mieć listę wpisów w pamięci, powinieneś używać scandir.

Nie ma sensu kopiowanie informacji do pamięci, kiedy i tak zamierzamy go używać. Leniwa ocena jest zdecydowanie drogą do zrobienia w tej sprawie.

Wyobrażam sobie, że scandir jest po prostu opakowaniem tego samego, co wywołuje readdir, a zatem będzie wolniejsze.

2

Czy trochę więcej porównań czasowych na czytanie całe drzewo katalogów z dużą ilością plików i katalogów:

  • wywołanie filetype() == „dir” jest wyraźnie szybszy niż is_dir() wezwanie

  • się opendir/readdir połączenia są znacznie szybsze niż budynku RecursiveDirectoryIterator

  • drzewo katalogów za pomocą pierwszego lub liniowy głębokość rekurencji połączeń sprawia, że ​​nie ma różnicy

Powyższe testy przeprowadzone w systemie Windows, gdzie na lokalnym dysku SSD, USB i lokalnym dysku sieciowego z spójnych wyników. Praca na dysku sieciowym była do 180 razy wolniejsza niż dysków lokalnych - mimo gigabitowej i poza tym szybkiej jednostki ReadyNAS!

Liczba wpisów przetwarzanych na sekundę wahała się od 115, a najwolniejszy kod na dysk sieciowy do prawie 65 000 dla najszybszego kodu na dysku USB 3.0 - z powodu oczywiście buforowania.

Ale ogromna różnica w napędzie sieciowym sprawia, że ​​zastanawiasz się, co dzieje się wewnątrz PHP, jako proste polecenie dir, a ls w Linuksie na tych samych plikach jest znacznie szybszy.

Aby kontynuować ...

2

Zrobiłem kilka testów. (Dzięki Aufziehvogel na budowie)

$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 Wyniki Server:

scandir: 0.82553291320801 
readdir: 0.91677618026733 
glob : 0.76309990882874 

Ten Reasults z 4 rdzeni (8 wątków) intel E3-1240 Cpu Linux + Apache serwerów.

Jednak wyniki serwerów Windows są odwrotne. Serwer Windows + Apache - Intel Q8400 4 rdzeniowy (4 wątki)

Okna Wyniki Server:

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

scandir: 0.61557507515 
readdir: 0.614650011063 
glob : 1.92112612724 

(Folder zawiera 13 plików Jeśli pliki jest wzrost, wyniki mogą być różne).

2

wiem to pytanie może nie być aktualne, ale aby dołączyć, zrobiłem kilka testów (takich jak Aufziehvogel i Sayahan) z niewielką różnicą - w katalogu z 1 000 000 małych (kilka bajtów) plików.

$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; 

Wyniki (HDD):

scandir:   1.9403479099274 
readdir:   0.79462885856628 
DirectoryIterator: 0.5853099822998 

Wyniki (SSD):

scandir:   0.83593201637268 
readdir:   0.35835003852844 
DirectoryIterator: 0.28022909164429 

CPU: AMD A10-4600M APU z Radeon (TM) HD Graphics (4 rdzenie)
MEM: 8G
PHP: 5.6.29