PHP中的c-scandir()太慢了


c - scandir() in PHP far too slow

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

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

我需要打开并处理每个文件,然后才能把它塞进桌子。fyi。我不能等待超过1-2秒的时间来处理阵列。感谢任何协助。内存不是问题。hdd空间不是问题,处理器功率也不是问题。问题是在使用网页前端时快速获取数组中的列表。我等不及了,因为我等厌了。

我试着用opendirreaddir使用一个简短的快速c程序,但扫描目录列表几乎需要4分钟。至少我可以设置一个调控器来限制x个文件。

答案似乎是调用perlc程序,我可以将其限制为x个文件,我可以用system()backticks调用它。然后可以用file()打开该列表。。。OTF。。。有道理吗?

问题是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。这将把单个目录中的文件数量减少到文件系统可以更好地处理的级别。

您可以编写一个调用getdents系统调用的C程序。使用大的缓冲区大小,比如5MB,并跳过索引节点==0的条目,以显著提高性能。

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

下面链接的Olark Developers Corner博客介绍了这种方法。

参考文献:

  • http://be-n.com/spw/you-can-list-a-million-files-in-a-directory-but-not-with-ls.html旧链接
  • http://man7.org/linux/man-pages/man2/getdents.2.html