3

我有一个巨大的日志文件(大约 5-10 百万行)。我需要遍历每一行并进行处理。我看到了巨大的运行时间。

我知道两种读取文件的方法,perl如下所示。

(1)如何比较不同方法的性能?任何基准机制?

(2)什么是最有效的方法,为什么?有没有第三种更好的方法可用?

一种选择是实现这两种方法并检查运行时。但在这里我试图了解是什么让他们跑得更快或更慢。如果您能在这方面帮助我,将不胜感激。

方法一

open FOPEN, '<', $file or die $!;
my @lines = <FOPEN>;
chomp @lines;
foreach (@lines) {
    # do something on $_
}

方法二

open FOPEN, '<', $file or die $!;
while (<FOPEN>) {
    chomp;
    # do something on $_
}
4

3 回答 3

8

方法2绝对是要走的路。方法 1 会将整个文件复制到内存中(在变量 @lines 内)。如果您的日志文件大于 1 GB,预计您的程序会崩溃。方法 2 将逐行遍历文件,并保持近乎恒定的内存使用量。

希望这可以帮助。

编辑:(忘了谈论基准测试部分)

您可以使用Benchmark之类的模块来比较这两种方法在多次迭代中的性能。一个非常方便的工具。您会发现方法 2 在处理非常大的文件时比方法 1 的性能要好很多。

于 2013-09-28T12:19:28.953 回答
8

除非您需要乱序处理文件的行,否则您绝对应该循环读取它while,因为将整个文件吸收到一个数组中只会浪费内存。Perl IO 系统将通过缓冲文件读取并在请求时从缓冲区传递每一行数据,从而使其尽可能高效。

也可能不需要chomp每一行。字符串末尾的备用换行符不太重要。

根据您要对文件执行的操作,将输入预处理为仅包含感兴趣信息的较小文件(或多个文件)可能是合适的。

始终使用词法文件句柄,即

open my $fh, '<', $file or die $!;
while (<$fh>) {
    # do something on $_
}

这与效率无关;这只是一个很好的做法。

于 2013-09-28T12:27:12.443 回答
1

如果文件很大并且您正在读取整个文件,请考虑使用无阻塞 IO 进行 sysread,此处可以找到一些示例:http: //docstore.mik.ua/orelly/perl/cookbook/ch07_15.htm 或搜索“ perl sysread 非阻塞”

于 2013-09-28T18:57:37.033 回答