我有一个巨大的日志文件(大约5-10万行)。我需要遍历每一行并进行处理。我看到了巨大的运行时间。
我知道有两种方法可以在perl
中读取文件,如下所示。
(1)如何比较不同方法的效果?任何基准标记机制?
(2)最有效的方法是什么?为什么?是否有第三个和更好的方法?
一种选择是实现这两种方法并检查运行时。但在这里,我试着了解是什么让他们跑得更快或更慢。如果你能在这方面帮助我,那将是值得的。
方法1
open FOPEN, '<', $file or die $!;
my @lines = <FOPEN>;
chomp @lines;
foreach (@lines) {
# do something on $_
}
方法2
open FOPEN, '<', $file or die $!;
while (<FOPEN>) {
chomp;
# do something on $_
}
答案 0 :(得分:8)
除非你需要不按顺序处理文件的行,否则你应该肯定在while
循环中读取它,因为将整个文件吸收到数组中只会浪费内存。 Perl IO系统将通过缓冲文件读取并在请求时从缓冲区传递每行数据来提高效率。
每行可能也不需要chomp
。字符串末尾的备用换行符不太重要。
根据您对文件的处理方式,可能需要将输入预处理为仅包含感兴趣信息的较小文件(或多个文件)。
始终使用词汇文件句柄,即
open my $fh, '<', $file or die $!;
while (<$fh>) {
# do something on $_
}
这与效率无关;这只是一种很好的做法。
答案 1 :(得分:7)
方法2绝对是要走的路。方法1将整个文件复制到内存中(在变量@lines内)。如果您的日志文件是&gt; 1 GB,期望您的程序崩溃。方法2将逐行迭代文件,并保持几乎恒定的内存使用。
希望这有帮助。
编辑:(忘了谈基准部分)您可以使用Benchmark之类的模块来比较两种方法在多次迭代中的性能。一个非常方便的工具。你会发现方法2对于一个非常大的文件,会以合适的余量超出方法1。
答案 2 :(得分:1)
如果文件大小很大并且您正在读取整个文件,请考虑使用无阻塞IO的sysread,这里可以找到一些示例:http://docstore.mik.ua/orelly/perl/cookbook/ch07_15.htm 或搜索“perl sysread non blocking”