In your second example, you're using map in void context, which is generally considered a no-no. In general, foreach is for general-purpose looping, and map is more of a special-purpose type of foreach just for generating lists. You don't seem interested in generating another list as a result of this loop, so your first example is at least semantically clearer.
My hunch is that, even though map is in void context, it is still generating the return-list that is scalar(@objects) elements large. In your case, every element of this anonymous list is undef due to the last line of the block. To test this hunch, change the code to the following:
map { $module->target($_);
my $results = $module->process();
(); } @objects;
.. so that the return-list never gets added onto. See if that brings performance in line with the foreach (not that I'm encouraging you to stay with the void-context map here).. <runs off to benchmark...>
I am also under the impression that the second method should be faster. Is that true?
I highly doubt that, but don't know enough about the internals to say one way or another. Clearly (from your experience) in void context, map seems to have the extra overhead of maintaining the return-list.
PS: undef $results is not needed, as $results falls out of scope at the end of the block each time. But you probably just had that in to double-check your suspicion of a memory leak..
Update: Yep, the benchmark showed that there is a significant improvement by having (); as the last statement of the void-context map BLOCK:
use Benchmark 'cmpthese';
+
my @objects = (1 .. 100_000);
+
cmpthese( -1, {
map1 => sub { map { my $xyz = $_ + 1000; undef $xyz; } @objects; 1;
+},
map2 => sub { map { my $xyz = $_ + 1000; (); } @objects; 1;
+},
for => sub { for (@objects) { my $xyz = $_ + 1000; undef $xyz } 1;
+}
});
__END__
Benchmark: running for, map1, map2 for at least 1 CPU seconds...
for: 1 wallclock secs ( 1.10 usr + 0.01 sys = 1.11 CPU) @ 11
+.71/s (n=13)
map1: 1 wallclock secs ( 1.08 usr + 0.00 sys = 1.08 CPU) @ 7
+.41/s (n=8)
map2: 2 wallclock secs ( 1.06 usr + 0.00 sys = 1.06 CPU) @ 10
+.38/s (n=11)
Rate map1 map2 for
map1 7.41/s -- -29% -37%
map2 10.4/s 40% -- -11%
for 11.7/s 58% 13% --
.. My simple for loop was faster than both, but please avoid map in void context for semantic reasons alone.
blokhead |