让我们得到一些这方面的数据。我对每个人的技术进行了基准测试...
#!/usr/bin/env perl
sub flag_in_loop {
my $file = shift;
open my $fh, $file;
my $first = 1;
while(<$fh>) {
if( $first ) {
$first = 0;
}
else {
my $line = $_;
}
}
return;
}
sub strip_before_loop {
my $file = shift;
open my $fh, $file;
my $header = <$fh>;
while(<$fh>) {
my $line = $_;
}
return;
}
sub line_number_in_loop {
my $file = shift;
open my $fh, $file;
while(<$fh>) {
next if $. < 2;
my $line = $_;
}
return;
}
sub inc_in_loop {
my $file = shift;
open my $fh, $file;
my $first;
while(<$fh>) {
$first++ or next;
my $line = $_;
}
return;
}
sub slurp_to_array {
my $file = shift;
open my $fh, $file;
my @array = <$fh>;
shift @array;
return;
}
my $Test_File = "/usr/share/dict/words";
print `wc $Test_File`;
use Benchmark;
timethese shift || -10, {
flag_in_loop => sub { flag_in_loop($Test_File); },
strip_before_loop => sub { strip_before_loop($Test_File); },
line_number_in_loop => sub { line_number_in_loop($Test_File); },
inc_in_loop => sub { inc_in_loop($Test_File); },
slurp_to_array => sub { slurp_to_array($Test_File); },
};
由于这是 I/O,它可能会受到 Benchmark.pm 无法调整的力量的影响,所以我运行了几次并检查我得到了相同的结果。
/usr/share/dict/words
是一个 2.4 兆的文件,大约有 240k 非常短的行。由于我们不处理线条,因此线条长度无关紧要。
我在每个例程中只做了少量的工作来强调技术之间的差异。我想做一些工作,以便通过更改读取文件的方式来确定您将获得或失去多少性能的现实上限。
我在带有 SSD 的笔记本电脑上执行此操作,但它仍然是笔记本电脑。随着 I/O 速度的提高,CPU 时间变得更加重要。在具有快速 I/O 的机器上,技术更为重要。
这是每个例程每秒读取文件的次数。
slurp_to_array: 4.5/s
line_number_in_loop: 13.0/s
inc_in_loop: 15.5/s
flag_in_loop: 15.8/s
strip_before_loop: 19.9/s
我很震惊地发现它my @array = <$fh>
是最慢的。考虑到所有工作都在 perl 解释器中进行,我会认为这将是最快的。然而,它是唯一一个分配内存来保存所有行的,这可能是性能滞后的原因。
使用$.
是另一个惊喜。也许这就是访问魔法全局的成本,或者可能是进行数字比较。
而且,正如算法分析所预测的那样,将标头检查代码放在循环之外是最快的。但不是很多。如果您使用接下来的两个最快,可能还不足以担心。