As has been mentioned in previous questions of this sort, for is faster and requires less memory than map, because map creates a temporary in-memory list to return, which is then transformed into a hash. This effect is much more pronounced for large arrays than small ones... in fact, let's run some benchmarks:
use strict;
use warnings;
use Benchmark qw(cmpthese);
for my $size (5,50,500) {
my @lol = map { [$_, qw(some random useless data)] } (1..$size);
print "\n\nComparing 'map' and 'for' hash-assignment from array of $
+size elements\n";
cmpthese (-2, {
for => sub { my %hash; $hash{$_->[0]} = $_ for @lol; },
map => sub { my %hash; %hash = map{$_->[0] => $_} @lol; }
});
}
## OUTPUTS ##
Comparing 'map' and 'for' hash-assignment from array of 5 elements
Benchmark: running for, map, each for at least 2 CPU seconds...
for: 3 wallclock secs ( 2.22 usr + 0.00 sys = 2.22 CPU) @ 77
+311.15/s (n=171940)
map: 1 wallclock secs ( 2.19 usr + 0.00 sys = 2.19 CPU) @ 55
+606.20/s (n=122000)
Rate map for
map 55606/s -- -28%
for 77311/s 39% --
Comparing 'map' and 'for' hash-assignment from array of 50 elements
Benchmark: running for, map, each for at least 2 CPU seconds...
for: 2 wallclock secs ( 2.04 usr + 0.00 sys = 2.04 CPU) @ 99
+92.17/s (n=20414)
map: 2 wallclock secs ( 2.12 usr + 0.00 sys = 2.12 CPU) @ 56
+57.09/s (n=12010)
Rate map for
map 5657/s -- -43%
for 9992/s 77% --
Comparing 'map' and 'for' hash-assignment from array of 500 elements
Benchmark: running for, map, each for at least 2 CPU seconds...
for: 3 wallclock secs ( 2.01 usr + 0.00 sys = 2.01 CPU) @ 94
+8.83/s (n=1910)
map: 2 wallclock secs ( 2.07 usr + 0.00 sys = 2.07 CPU) @ 33
+5.75/s (n=696)
Rate map for
map 336/s -- -65%
for 949/s 183% --
For large arrays of 500 elements, using the seemingly innocuous map technique is nearly three times slower. For your typical 50-element array, map is almost twice as slow.
I'm actually surprised the performance penalty was so pronounced. | [reply] [d/l] [select] |
Your analysis while good in theory is off in details.
Judging by a comparison with a development Perl, map will
always be about twice as slow. Probably because of all
of the lists you create, then having to internally do the
assignments to the hash.
However the slow-down you wondered at with 500 elements is
the effect of the quadratic slowdown in my note. The
problem is that the entire argument stack was getting moved
for each call of the block. The first time that takes work
n. The second n-1. The third n-2. etc. So it is
quadratic.
If you are willing to recompile Perl, there is a very
simple patch
available.
| [reply] |