vp8*_*vp8 0 arrays perl performance
假设用户想要根据特定条件从数组中过滤元素.用户有两种选择.要么他可以使用一行grep语句,要么写一个for循环并根据特定条件存储元素.
例如
my @array = (1, 2, 3, 4, 5, 6, 7, 8);
选项1 : my @filtered = grep { $_/2 eq 0 } @array;
选项2:
foreach (@array)
{
if($_/2 eq 0) {
push @filtered, $_;
}
}
Run Code Online (Sandbox Code Playgroud)
如果性能是一个因素,哪种是首选的写作方式?
由于grep具有特定的优化,因此第一种选择通常必须更快.
但是,该陈述过于笼统,您需要对其进行基准测试,特别是在适用于您的工作的条件下.
使用Benchmark模块的示例
use warnings;
use strict;
use feature 'say';
use Getopt::Long;
use Benchmark qw(cmpthese);
my $time = 3;
my $size = 10_000;
GetOptions( 'time=i' => \$time, 'size=i' => \$size ) or usage();
sub w_grep {
my @res = grep { $_/2 > $size/4 } @{$_[0]};
return \@res;
}
sub w_for {
my @res;
for (@{$_[0]}) {
push @res, $_ if $_/2 > $size/4;
}
return \@res;
}
my @t = 1..$size;
cmpthese( -$time, {
grep => sub { w_grep(\@t) },
for => sub { w_for(\@t) },
});
sub usage {
say STDERR "Usage: $0 [--time NUM] [--size NUM]";
exit;
}
Run Code Online (Sandbox Code Playgroud)
大约一半时间条件都是正确的,因此标量会被创建并经常添加.创建大量标量是昂贵的,这可能是主要因素,您的条件是多么频繁.
它打印(在CentOS 7下的v5.16桌面上)
Rate for grep
for 948/s -- -13%
grep 1085/s 14% --
但是,如果我们让条件更具限制性$_/2 > $size/2,那么我们就得到了
Rate for grep
for 1217/s -- -6%
grep 1296/s 6% --
而当它大部分时间成功时,比如说$_/2 > 10,费率是
Rate for grep
for 945/s -- -28%
grep 1304/s 38% --
这表明for随着阵列的增加,进一步落后.
但是请记住,这取决于你在测试中做出的选择的许多其他方式,一些相当微妙,一些不那么微妙.
例如,首先解压缩arrayref(my @ary = @{ $_[0] };)会将差异减少到几个百分点,因为运行时主要是创建本地数组.这会引发你的测试 - 或者反映你的情况.您需要仔细选择您的条件.
当然,数量也随阵列大小,计算的复杂性等而变化.