如何加速Perl的readdir以获得250,000个文件的目录?

时间:2009-04-09 20:58:59

标签: performance perl readdir

我使用Perl readdir来获取文件列表,但是,该目录包含超过250,000个文件,这导致执行readdir并使用超过80MB的RAM的时间长(超过4分钟)。由于这是每5分钟一次的重复工作,因此这个滞后时间是不可接受的。

更多信息: 另一项工作将填写扫描目录(每天一次)。 此Perl脚本负责处理文件。为每个脚本迭代指定文件计数,目前每次运行1000次。 Perl脚本每5分钟运行一次并处理(如果适用)最多1000个文件。 文件计数限制旨在允许下游流处理随着Perl将数据推入数据库而触发复杂的工作流程。

是否有另一种从目录获取文件名的方法,理想情况下限制为1000(由变量设置),这会大大提高此脚本的速度?

6 个答案:

答案 0 :(得分:9)

当你说readdir需要几分钟和80 MB时,你究竟是什么意思?你能展示一下特定的代码吗?你在标量或列表上下文中使用readdir吗?

你在做这样的事情:

foreach my $file ( readdir($dir) ) { 
   #do stuff here
}

如果是这种情况,您正在将整个目录列表读入内存。难怪它需要很长时间和很多记忆。

本文的其余部分假设这是问题所在,如果您未在列表上下文中使用readdir,请忽略帖子的其余部分。

对此的修复是使用while循环并在标量上下文中使用readdir

while ( 
    defined( my $file = readdir $dir )
 ) {

    # do stuff.

}

现在您一次只能阅读一个项目。您可以添加计数器以跟踪您处理的文件数量。

答案 1 :(得分:7)

解决方案可能在另一端:在填充目录的脚本中......

为什么不创建一个arborescence来存储所有这些文件,这样有很多目录,每个目录都有可管理的文件数量?

而不是创建“mynicefile.txt”为什么不是“m / my / mynicefile”,或类似的东西?

您的文件系统会感谢您(尤其是当您完成它们时删除空目录)。

答案 2 :(得分:2)

这不是您的查询的答案,但我认为在相同的目录中拥有那么多文件对整体速度来说并不是一件好事(包括文件系统处理的速度)添加和删​​除操作,而不仅仅是您所看到的列表。

该设计问题的解决方案是为文件名的每个可能的第一个字母设置子目录,并在该目录中包含以该字母开头的所有文件。如果需要,可以递归到第二,第三等字母。

您可能会看到可能的操作速度明显改善。

答案 3 :(得分:2)

你说通过解压缩zip文件来获取内容。为什么不直接使用zip文件而不是在一个目录中创建/使用250k文件?

基本上 - 为了加快速度,你不需要在perl中使用特定的东西,而是在文件系统级别上。如果你100%确定你必须在目录中使用250k文件(我无法想象这种情况需要这样的事情) - 你找到更好的文件系统来处理它比找到更好perl中的一些“神奇”模块可以更快地扫描它。

答案 4 :(得分:1)

可能不是。我猜大部分时间都是在阅读目录条目。

但是,您可以预处理整个目录列表,每1000个条目创建一个文件。然后,您的进程每次都可以执行其中一个列表文件,而不会产生读取整个目录的费用。

您是否通过该目录尝试 readdir()而没有任何其他处理才能获得基线?

答案 5 :(得分:1)

您无法加速readdir,但您可以加快监控目录的任务。例如,您可以向操作系统询问更新 - 例如,Linux已经通知了。这是一篇关于使用它的文章:

http://www.ibm.com/developerworks/linux/library/l-ubuntu-inotify/index.html?ca=drs-

您可以使用Perl的Inotify:

http://metacpan.org/pod/Linux::Inotify2

不同之处在于您将拥有一个长期运行的应用程序,而不是由cron启动的脚本。在应用程序中,您将保留一个新文件队列(由inotify提供)。然后,将计时器设置为每5分钟关闭一次,并处理1000个项目。之后,控制权返回到事件循环,您可以在5分钟后唤醒并处理1000多个项目,或者inotify会向您发送更多文件以添加到队列中。

(顺便说一句,你需要一个事件循环来处理定时器;我建议使用EV。)

相关问题