Your Foreach test uses map, and your Map test uses foreach. You're making me dizzy. After fixing the test names and running the test for 10 seconds, foreach was 76% faster than map:
Rate Map Foreach
Map 21.9/s -- -43%
Foreach 38.6/s 76% --
Foreach is faster as expected, since foreach doesn't have to build a long list like map does. Update: I wrote a foreach loop that builds an array which is later assigned to %hash. As you can see below, "Map" and "Map-like" have very similar results, as expected.
use strict;
use Benchmark ();
Benchmark::cmpthese(-10, {
"Map" => sub { my %hash = map{$_=>1} (1..10000); },
"Foreach" => sub { my %hash; $hash{$_} = 1 foreach (1..10000); },
"Map-like" => sub { my @a; push(@a, $_, 1) foreach (1..10000);
my %hash = @a; },
})
__END__
Rate Map-like Map Foreach
Map-like 21.5/s -- -1% -44%
Map 21.8/s 1% -- -43%
Foreach 38.6/s 80% 77% --
| [reply] [d/l] [select] |
| [reply] [d/l] |
| [reply] [d/l] [select] |
Assuming the goal is just to create the hash keys, you left out:
"Undef' => sub { my %hash; undef @hash{1..10000}; }
| [reply] [d/l] |
As brian d foy pointed out, you're not doing the same thing. Furthermore, you're using a blocked map, vs a foreach statement modifier. If you want to be fair, you should to the same thing. Below is a benchmark that does the same thing in all cases. It also compares the block form and the expression form. And to top it off, all the cases appear as a coderef, and as a string.
#!/usr/bin/perl
use strict;
use warnings;
use Benchmark qw /cmpthese/;
cmpthese(-1, {
m_exp1 => sub {my %hash; map $hash{$_} = 1, 1 .. 10_000},
m_blk1 => sub {my %hash; map {$hash{$_} = 1} 1 .. 10_000},
f_exp1 => sub {my %hash; $hash{$_} = 1 foreach 1 .. 10_000},
f_blk1 => sub {my %hash; foreach (1 .. 10_000) {$hash{$_} = 1}},
m_exp2 => 'my %hash; map $hash{$_} = 1, 1 .. 10_000',
m_blk2 => 'my %hash; map {$hash{$_} = 1} 1 .. 10_000',
f_exp2 => 'my %hash; $hash{$_} = 1 foreach 1 .. 10_000',
f_blk2 => 'my %hash; foreach (1 .. 10_000) {$hash{$_} = 1}',
});
__END__
Rate m_blk2 m_exp2 f_blk1 m_exp1 f_blk2 f_exp2 f_exp1 m_blk1
m_blk2 38.0/s -- -5% -7% -9% -10% -10% -13% -14%
m_exp2 39.8/s 5% -- -2% -5% -5% -6% -9% -10%
f_blk1 40.7/s 7% 2% -- -3% -3% -4% -7% -8%
m_exp1 41.9/s 10% 5% 3% -- -0% -1% -4% -5%
f_blk2 42.1/s 11% 6% 3% 0% -- -1% -4% -5%
f_exp2 42.3/s 11% 6% 4% 1% 1% -- -3% -4%
f_exp1 43.8/s 15% 10% 8% 5% 4% 4% -- -1%
m_blk1 44.2/s 17% 11% 9% 6% 5% 5% 1% --
There's no significant difference. Note that the map-block form is both the fastest and the slowest (fastest in the sub form, slowest in the string form, although there's an overhead when calling subs).
This was done with perl 5.8.6. With older perls, you might find map to be slower. | [reply] [d/l] |
Benchmark could have been more informative if perl version, machine load status and such had been given.
Using ikegami's code, perl 5.8.5 (FreeBSD/i386, 4.9-p11) gives on a quite idle machine (386MB RAM, 700MHz CPU, FreeBSD 4.10-p5) ...
Rate Map-like Map Foreach
Map-like 8.69/s -- -2% -29%
Map 8.90/s 2% -- -27%
Foreach 12.3/s 41% 38% --
... which obviously confirms that overall foreach is indeed faster than
map.
| [reply] [d/l] [select] |
ActivePerl 5.8.0 or 5.8.1, WinXP, P4/2.66GHz, 1GB RAM, idle machine
| [reply] |