读取包含数百万个文件的目录时perl内存不足

时间:2015-04-14 06:06:07

标签: perl

我在AMD 64上使用Strawberry Perl并试图简单地读取包含数百万个文件的文件夹。这是一个NTFS驱动器。这段代码将运行几分钟,并且进程中的内存会一直增长,直到我最终得到“Out of Memory!”。关于为什么会出现内存的任何想法都会有所帮助,但我想知道这是否是一个真正的问题?

    #!/usr/bin/perl
    use strict;

    my $dir = '../svcUploadedFiles';
    my $file = '';
    opendir(DIR, $dir) or die $!;
    while ($file = readdir(DIR)) {

    }
    closedir(DIR);
    exit 0;

1 个答案:

答案 0 :(得分:1)

我怀疑这里的罪魁祸首是readdir,但没有任何关于print是否有任何区别的信息,我无法确定。

Perl必须支持rewwinddirtelldirseekdir以及简单的readdir,因此我认为它将整个目录列表保留在内存中以方便这一点。

但是,我已经在一个包含6M文件的目录上运行你的代码,并且该进程的大小只有大约80MB,所以除非你的文件比这个文件多得多,否则它们的名字都比较长(这些都是大约12个字符) )然后我仍然无法解释这个问题。

解决问题的方法可能是从运行cmd.exe命令的dir /b进程打开管道。这将一次为您的主进程传递一个文件名,并且内存负载将在子进程上,因此不应该是一个问题。


<强>更新

好的,所以你的文件数量大约是我的两倍,所以让我们猜测160MB,这对于Perl进程来说应该不是问题。您的文件名称有多长,简化过程有多大?

这是一个Perl程序示例,它从dir的输出中读取,而不是使用内部readdir。它使Perl进程大约为3.6MB,rh cmd.exe进程只有1MB以上。它比readdir慢得多,但我无法想到另一种阅读和处理目录的方式,它应该是一个简单的替代品

use strict;
use warnings;
use 5.010;
use autodie;

my $dir = '../svcUploadedFiles';

open my $cmd_fh, '-|', qq{cmd /c dir /b "$dir"};

open my $file_fh, '>', 'filelist.txt';

while ( my $file = <$cmd_fh> ) {
  chomp $file;
  print $file_fh "$file\n";                
}

close $file_fh;                   

close $cmd_fh;