【发布时间】:2014-05-01 15:13:41
【问题描述】:
在网上长时间搜索后,我决定在这里询问我的问题。我有一个 CSV 文件集(总共 36 个文件),每 5 分钟发送一次。每个文件包含大约 150 万行。我需要在 5 分钟内处理这些文件。我必须解析这些文件并在存储区域内从它们创建所需的目录。然后每个唯一的行将被翻译成一个文件并放在相关目录中。相关行也将写入相关文件中。如您所见,有很多 I/O 操作。
我可以在大约 10 分钟内完成总共 12 个文件。目标是在 5 分钟内完成 36 个。我正在使用 PERL 来完成这个操作。我看到的问题是 i/o 操作的系统调用。
我想在 Perl 中控制文件处理程序和 I/O 缓冲区,这样我就不必每次都去写入文件。这是我真正迷路的地方。加上创建目录似乎也消耗了太多时间。
我在 CPAN 和网络上搜索了一些线索,可以照亮我的道路,但没有运气。有人对那个主题有建议吗?我应该在哪里阅读或应该如何进行?我相信 Perl 完全有能力解决这个问题,但我想我没有使用正确的工具。
open(my $data,"<", $file);
my @lines = <$data>;
foreach (@lines) {
chomp $_;
my $line = $_;
my @each = split(' ',$line);
if (@each == 10) {
my @logt = split('/',$each[3]);
my $llg=1;
if ($logt[1] == "200") {
$llg = 9;
}
my $urln = new URI::URL $each[6];
my $netl = $urln->netloc;
my $flnm = md5_hex($netl);
my $urlm = md5_hex($each[6]);
if ( ! -d $outp."/".$flnm ) {
mkdir $outp."/".$flnm,0644;
}
open(my $csvf,">>".$outp."/".$flnm."/".$time."_".$urlm) or die $!;
print $csvf int($each[0]).";".$each[2].";".$llg."\n";
close $csvf; #--->> I want to get rid of this so I can use buffer
}
else {
print $badf $line;
}
}
假设上面的代码在一个子程序中使用并且线程化了 12 次。上述代码的参数是 filename 。我想摆脱关闭。因为每次我打开和关闭文件时都会调用系统 I/O,这会导致速度变慢。这当然是我的假设,我更愿意接受任何建议
提前致谢
【问题讨论】:
-
你在使用
system()复制文件和制作目录吗? -
您是否已将其并行化,以便您的(可能的)4 个内核中的每一个可能获得 9 个文件?您是否使用出色的 search.cpan.org/perldoc/Devel::NYTProf 分析了您的代码
-
cat *csv > /dev/null需要多长时间? -
您正在为 5400 万行中的每一行打开一个要追加的文件...
-
我上一个问题的原因是我认为您最好将数据保存在内存中,然后最后全部写入磁盘。因此,使用文件名作为键创建一个散列,并将数据附加到散列元素的末尾,而不是写入文件。然后,当你到最后,或者你觉得内存中有足够的东西时,将它们全部刷新到真正的磁盘文件中。