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


In reply to Re: Memory leak in map function? by blokhead
in thread Memory leak in map function? by ezekiel

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.