amon 的copy
速度可以调整为 30%!
my $i = 1;
my $j = 1;
while ($i < @a) {
$a[++$j] = $a[$i+=2];
$a[++$j] = $a[++$i];
}
$#a = $j-1 if @a>2;
并且您可以通过完全避免复制任何内容来获得更快的速度(尽管结果是对数组的引用)。每个元素中的字符串越长,效果就越好。
my $i = 0;
my $ref = sub { \@_ }->( grep { ++$i % 3 } @a );
结果(10,000 个元素):
>perl a.pl
Rate splice_a splice_r grep_a copy1_a copy1_r copy2_r copy2_a grep_r
splice_a 52.8/s -- -0% -51% -54% -56% -66% -66% -68%
splice_r 52.9/s 0% -- -51% -54% -55% -66% -66% -68%
grep_a 107/s 103% 103% -- -7% -10% -30% -31% -34%
copy1_a 115/s 118% 117% 7% -- -3% -25% -26% -30%
copy1_r 119/s 125% 124% 11% 3% -- -23% -23% -27%
copy2_r 154/s 191% 190% 43% 34% 29% -- -0% -6%
copy2_a 154/s 192% 192% 44% 34% 30% 0% -- -6%
grep_r 163/s 209% 209% 52% 42% 37% 6% 6% --
基准:
use strict;
use warnings;
use Benchmark qw( cmpthese );
my @testlist = qw( helloworld sessions first.cgi login localpcs depthhashes.cgi search view macros );
@testlist = ( @testlist ) x ( 10000 / @testlist );
sub grep_a { my @a = @testlist; my $i = 0; @a = grep { ++$i % 3 } @a; 1 }
sub copy1_a { my @a = @testlist;
my @b;
$#b = $#a; @b = (); # Does absolutely nothing in this benchmark because of optimisations in Perl.
for (my $i = 0; $i < @a; $i += 3) {
push @b, @a[$i, $i+1];
}
1
}
sub copy2_a { my @a = @testlist;
my $i = 1;
my $j = 1;
while ($i < @a) {
$a[++$j] = $a[$i+=2];
$a[++$j] = $a[++$i];
}
$#a = $j-1 if @a>2;
1
}
sub splice_a { my @a = @testlist;
for (my $i = 2; $i < $#a; $i += 2) {
splice @a, $i, 1;
}
1
}
sub grep_r { my $r = [ @testlist ]; my $i = 0; $r = sub { \@_ }->( grep { ++$i % 3 } @$r ); 1 }
sub copy1_r { my $r = [ @testlist ];
my @b;
$#b = $#$r; @b = (); # Does absolutely nothing in this benchmark because of optimisations in Perl.
for (my $i = 0; $i < @$r; $i += 3) {
push @b, @$r[$i, $i+1];
}
$r = \@b;
1
}
sub copy2_r { my $r = [ @testlist ];
my $i = 1;
my $j = 1;
while ($i < @$r) {
$r->[++$j] = $r->[$i+=2];
$r->[++$j] = $r->[++$i];
}
$#$r = $j-1 if @$r>2;
1
}
sub splice_r { my $r = [ @testlist ];
for (my $i = 2; $i < $#$r; $i += 2) {
splice @$r, $i, 1;
}
1
}
cmpthese(-3, {
grep_a => \&grep_a,
copy1_a => \©1_a,
copy2_a => \©2_a,
splice_a => \&splice_a,
grep_r => \&grep_r,
copy1_r => \©1_r,
copy2_r => \©2_r,
splice_r => \&splice_r,
});