我在Perl中是个新手,我想知道以下哪个循环更有效:
my @numbers = (1,3,5,7,9);
foreach my $current (@numbers){
print "$current\n";
}
或者
my @numbers = (1,3,5,7,9);
foreach (@numbers){
print "$_\n";
}
我想知道这一点,以便知道$ _的使用是否更有效,因为它是否经常使用而被放置在寄存器中。我已经编写了一些代码,并且试图对其进行清理,发现与第二个循环相比,我使用第一个循环的频率更高。
最佳答案
甚至知道过早的优化是万恶之源
{
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";