++ for correcting the benchmark (I actually wouldn't have guessed that log could weight so much on the result).
There are still two issues with your benchmark though. First, you forgot the comma in @b = map log @a;, which is parsed as @b = map(log(@a)) where an empty @b is obtained. I have no idea why this is not a syntax error though. Second, the for-loops variant do not use the precomputed values, but compute the logarithm on each iteration.
With this benchmark:
use strict;
use warnings;
use Benchmark qw/ cmpthese /;;
for my $count ( 100, 1_000, 10_000, 100_000 ) {
my @array = map { log } 2 .. $count;
print "-" x 10, "\nWith $count elements\n";
cmpthese( -5, {
1 => sub {
my %h;
keys %h = @array;
$h{ $_ } = $_ for @array;
return \%h
},
2 => sub {
my %h;
$h{ $_ } = $_ for @array;
return \%h
},
3 => sub {
my %h;
keys %h = @array;
@h{ @array } = @array;
return \%h
},
4 => sub {
my %h;
@h{ @array } = @array;
return \%h
},
});
}
__DATA__
----------
With 100 elements
Rate 2 3 1 4
2 6956/s -- -2% -3% -5%
3 7103/s 2% -- -1% -3%
1 7162/s 3% 1% -- -2%
4 7321/s 5% 3% 2% --
----------
With 1000 elements
Rate 2 4 1 3
2 621/s -- -3% -4% -7%
4 638/s 3% -- -1% -4%
1 644/s 4% 1% -- -4%
3 668/s 7% 5% 4% --
----------
With 10000 elements
Rate 2 4 3 1
2 62.1/s -- -0% -3% -4%
4 62.3/s 0% -- -3% -3%
3 63.9/s 3% 3% -- -1%
1 64.5/s 4% 3% 1% --
----------
With 100000 elements
Rate 2 4 1 3
2 4.75/s -- -3% -6% -7%
4 4.89/s 3% -- -3% -4%
1 5.03/s 6% 3% -- -1%
3 5.08/s 7% 4% 1% --
We can see that in this case, slicing is just a little faster than iterating. Your benchmark did answer vr's question though: slicing does not seem to include the preallocation optimization. |