即使知道过早的优化是万恶之源
{
local $\ = "\n";
print foreach @numbers;
}
但有些期望可能是错误的。测试有点奇怪,因为输出会产生一些奇怪的副作用,而且顺序很重要。
#!/usr/bin/env perl
use strict;
use warnings;
use Benchmark qw(:all :hireswallclock);
use constant Numbers => 10000;
my @numbers = (1 .. Numbers);
sub no_out (&) {
local *STDOUT;
open STDOUT, '>', '/dev/null';
my $result = shift()->();
close STDOUT;
return $result;
};
my %tests = (
loop1 => sub {
foreach my $current (@numbers) {
print "$current\n";
}
},
loop2 => sub {
foreach (@numbers) {
print "$_\n";
}
},
loop3 => sub {
local $\ = "\n";
print foreach @numbers;
}
);
sub permutations {
return [
map {
my $a = $_;
my @f = grep {$a ne $_} @_;
map { [$a, @$_] } @{ permutations( @f ) }
} @_
]
if @_;
return [[]];
}
foreach my $p ( @{ permutations( keys %tests ) } ) {
my $result = {
map {
$_ => no_out { sleep 1; countit( 2, $tests{$_} ) }
} @$p
};
cmpthese($result);
}
可以预期 loop2 应该比 loop1 快
Rate loop2 loop1 loop3
loop2 322/s -- -2% -34%
loop1 328/s 2% -- -33%
loop3 486/s 51% 48% --
Rate loop2 loop1 loop3
loop2 322/s -- -0% -34%
loop1 323/s 0% -- -34%
loop3 486/s 51% 50% --
Rate loop2 loop1 loop3
loop2 323/s -- -0% -33%
loop1 324/s 0% -- -33%
loop3 484/s 50% 49% --
Rate loop2 loop1 loop3
loop2 317/s -- -3% -35%
loop1 328/s 3% -- -33%
loop3 488/s 54% 49% --
Rate loop2 loop1 loop3
loop2 323/s -- -2% -34%
loop1 329/s 2% -- -33%
loop3 489/s 51% 49% --
Rate loop2 loop1 loop3
loop2 325/s -- -1% -33%
loop1 329/s 1% -- -32%
loop3 488/s 50% 48% --
有时我一直观察到 loop1 比 loop2 快大约 15%-20%,但我无法确定原因。
我观察到为 loop1 和 loop2 生成了字节码,在创建 my 变量时只有一个不同。这个变量内部没有分配也没有复制,因此这个操作非常便宜。我认为差异来自"$_\n" 构造,它并不便宜。这些循环应该非常相似
for (@numbers) {
...
}
for my $a (@numbers) {
...
}
但这个循环更昂贵
for (@numbers) {
my $a = $_;
...
}
还有
print "$a\n";
比
贵
print $a, "\n";