readdir vs scandir

时间:2012-01-01 10:54:36

标签: php

1]哪个功能更快?
2]有什么区别?

Differences

  

1] readdir返回目录中下一个条目的名称。 Scandir从目录中返回一组文件和目录。

     

2] readdir必须打开资源句柄,直到读取所有条目。 scandir,也许会创建一个包含所有条目的数组并关闭资源句柄?

5 个答案:

答案 0 :(得分:15)

这实际上取决于您对数据做了什么。

如果您正在逐个输入,那么您应该使用readdir,如果您确实需要在内存中有一个条目列表,那么您应该使用scandir。< / p>

无论如何,当你打算逐个使用它时,将信息复制到内存中是没有意义的。在这种情况下,懒惰的评估绝对是可行的方法。

我认为scandir只是readdir调用的同一个包装器的包装器,因此会更慢。

答案 1 :(得分:14)

只是得到结果(没有做任何事情),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()编写另一个循环,它将会更慢。

答案 2 :(得分:4)

我知道这个问题现在可能不是真实的,但是为了追加我已经做了一些测试(比如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:具有Radeon(tm)HD Graphics(4核)的AMD A10-4600M APU
MEM:8G
PHP:5.6.29

答案 3 :(得分:3)

对于使用大量文件和目录读取整个目录树进行了更多的时序比较:

  • 通话 filetype()==&#34; dir&#34; 明显比is_dir()通话快

  • opendir / readdir 调用比RecursiveDirectoryIterator快得多

  • 使用递归调用深度优先或线性构建目录树没有区别

上述测试是在Windows上在本地SSD,本地USB和网络驱动器上执行的,具有一致的结果。在网络驱动器上运行速度比本地驱动器慢180倍 - 尽管千兆位和其他快速ReadyNAS单元!

每秒处理的条目数从最慢的代码115到网络驱动器的范围到最快的代码到USB 3.0驱动器的近65 000 - 当然是由于缓存。

但是网络驱动器的巨大差异让你想知道PHP内部会发生什么,因为简单的dir命令和Linux中相同文件的ls要快得多。

继续......

答案 4 :(得分: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

这个来自4核(8个线程)的英特尔E3-1240 Cpu linux + Apache服务器。

但Windows服务器的结果却相反。 Windows + Apache服务器 - 英特尔Q8400 4核(4线程)

Windows Server结果:

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

scandir: 0.61557507515
readdir: 0.614650011063
glob   : 1.92112612724

(文件夹包含13个文件。如果文件增加,结果可能不同)