PHP中的scandir()太慢了

时间:2015-03-27 04:21:50

标签: php c perl scandir readdir

目标目录有1000万个+文本文件。网页中的using $a = scandir()速度非常慢。需要数组结果不到两秒钟。过滤不起作用(也扫描整个列表)

我能想到的是使用perlc程序将目标目录中的x千个文件名预处理并填充到文件中,标记目标目录中的文件名。 .pi最后(或其他)并使用php的file()函数来获取文件中的列表。

我需要打开并处理每个文件,然后才能填入表格。仅供参考。我不能等待超过1-2秒才能使阵列工作。 任何协助赞赏。记忆不是问题。 hdd空间不是问题,处理器能力不是问题。问题是在使用网页前端时快速获取阵列中的列表。我不能等,因为我厌倦了等待。

我尝试使用带有opendirreaddir的简短快速c程序,但即使扫描目录列表也需要将近4分钟。至少我可以把一个调控器放到它上面来限制x文件。

似乎答案是调用perlc程序,我可以将其限制为x文件,我可以使用system()backticks来调用此程序。然后可以使用file()打开该列表... OTF ......有意义吗?

2 个答案:

答案 0 :(得分:7)

问题是PHP和文件系统越来越少。大多数文件系统在单个目录中不能很好地处理1000万个文件,性能开始受到严重影响。你不可能通过在C或Perl中重写它来获得更好的性能,因为文件系统简直不堪重负并且其性能已经变得病态。

首先,从scandir切换到opendirreaddir。这避免了必须制作1000万个元素阵列。它还可让你的程序在费力阅读1000万个文件名之前立即开始工作。

if ($dh = opendir($dir)) {
    while (($file = readdir($dh)) !== false) {
        ...do your work...
    }
    closedir($dh);
}

其次,根据文件名的第一个字母重构目录,使其至少具有两个级别的子目录。例如,t/h/this.is.an.example。这样可以将单个目录中的文件数量减少到文件系统可以更好地处理的水平。

答案 1 :(得分:3)

您可以编写一个调用C系统调用的getdents程序。使用较大的缓冲区大小(例如5MB),并跳过inode == 0的条目以显着提高性能。

依赖libc readdir()的解决方案很慢,因为它一次只能读取32K块目录条目。

此方法在下面链接的Olark Developers Corner博客中进行了描述。

参考文献: