【问题标题】:scandir() in PHP far too slowPHP 中的 scandir() 太慢了
【发布时间】:2015-03-27 04:21:49
【问题描述】:

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

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

我需要先打开并处理每个文件,然后才能将其塞入表格中。供参考。我不能等待超过 1-2 秒才能使阵列可用。 任何帮助表示赞赏。内存不是问题。 hdd 空间不是问题,处理器能力不是问题。问题是在使用网页前端时快速获取数组中的列表。我等不及了,因为我厌倦了等待。

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

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

【问题讨论】:

  • 任何包含 1000 万个文件的单个目录都会很慢——慢得可怕。根据经验,一千个文件太多了。您需要重新组织目录,而不是担心在 C 中重新实现(scandir() 也在 C 中实现 - 不会有太大区别)。
  • 是的,想到了……你是对的,我可能不得不在汇编中重写它,当我让它工作时,scandir() 就完成了:-)
  • 您将在程序集中使用opendir()readdir() 系统调用,它们会花费很长时间。您可能需要多层目录层次结构。一个简单的方案是将第一个字符用于第一层,将第二个(或第一和第二个字符)用于第二层,并根据系统的大小,可能将第三个(或第一到第三个字符)用于第三层。如果前三个字符是字母并且或多或少均匀分布在 26 个字母的字母表中(不太可能),那么每个第三级子子目录最终会有大约 600 个文件。
  • 你使用的是什么文件系统?
  • 谢谢各位!在此期间将大多数文件转储到 tmp 文件夹解决方法。 php 的 scandir() 一次可以很好地处理 200K 文件 C 解决方案是定义最终方向...保姆工作还不错...一旦 scandir() 执行了 200K 文件块,另一个 200k 块被移入,等等,这避免了现在重写测试代码。我在 /var 分区上使用 XFS FS,在 7TB raid 5 阵列上使用 Fedora 21 OS,该阵列由我在 eBay 上以 80 美元购买的 5805Z Adaptec 卡控制。所有人都对这个设置感到满意。它基本上是一个高级商品服务器......

标签: php c perl scandir readdir


【解决方案1】:

问题在于更少的 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。这会将单个目录中的文件数量减少到文件系统可以更好地处理的水平。

【讨论】:

    【解决方案2】:

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

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

    下面链接的 Olark Developers Corner 博客中描述了这种方法。

    参考资料:

    【讨论】:

      猜你喜欢
      • 2020-05-31
      • 1970-01-01
      • 1970-01-01
      • 2013-03-10
      • 2014-06-07
      • 2016-05-31
      • 2011-07-07
      • 2015-08-23
      • 2012-07-05
      相关资源
      最近更新 更多