Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Re^2: Map Vs Foreach

by perlCrazy (Monk)
on Nov 26, 2009 at 09:35 UTC ( #809513=note: print w/ replies, xml ) Need Help??


in reply to Re: Map Vs Foreach
in thread Map Vs Foreach

Thanks for reply. i did some benchmarking and found that map is slower than foreach.
Also I was under impression that map is actually faster than foreach, but my result is different !

#!/opt/gsperl-5.8.6_1/bin/perl use strict; use Benchmark; my ($start,$end,$diff); my @data = (1..20000000); # start timer $start = new Benchmark; my %dataseen; my @arr; foreach my $x (@data) { push @arr, ($x+2); } # end timer $end = new Benchmark; # calculate difference my $diff = timediff($end, $start); # report print "Time taken by foreach loop was ", timestr($diff, 'all'), " seco +nds\n"; my $start1 = new Benchmark; my @arr1; @arr1 = map { push @arr1, ($_+ 2) } @data; # end timer my $end1 = new Benchmark; # calculate difference my $diff1 = timediff($end1, $start1); # report print "Time taken by map block was ", timestr($diff1, 'all'), " second +s\n";
and output of code :
Time taken by foreach loop was 9 wallclock secs ( 8.22 usr 0.32 sys + 0.00 cusr 0.00 csys = 8.54 CPU) seconds
Time taken by map block was 15 wallclock secs (14.88 usr 0.72 sys + 0.00 cusr 0.00 csys = 15.60 CPU) seconds


Comment on Re^2: Map Vs Foreach
Download Code
Re^3: Map Vs Foreach
by cdarke (Prior) on Nov 26, 2009 at 09:59 UTC
    For what its worth:
    I was unhappy about your benchmark, since the two types of code did not appear to be the same:
    @arr1 = map { push @arr1, ($_+ 2) } @data;
    in particular seemed suspect to me. Also the order of memory allocation can affect benchmarks. When I ran the supplied code the foreach loop worked fine (5 seconds on my machine) but the map gave Out of memory!.

    So I rewrote each part to be a subroutine, and tided the map so it looked like this:
    sub mapsub { my @arr; @arr = map { ($_ + 2) } @data; }
    I can't say if that was faster, because it still gives Out of memory! Must be something to do with a temporary list (5.10.1 on Windows). Reducing the size of @data by a factor of 10 gives map taking around twice as long, and each taking under a second.
      Some more benchmarking:
      my @data = (1..8000000); foreach my $x (@data) { push @arr, ($x+2); } @arr1 = map { $_+ 2 } @data; @arr2 = map { push @arr2, ($_+ 2) } @data;
      resulted in the following measurement-output:

      Time taken by foreach loop was 2 wallclock secs ( 2.27 usr 0.03 sys + 0.00 cusr 0.00 csys = 2.30 CPU) seconds
      Time taken by map block was 4 wallclock secs ( 3.39 usr 0.34 sys + 0.00 cusr 0.00 csys = 3.73 CPU) seconds
      Time taken by map block (with push) was 5 wallclock secs ( 4.63 usr 0.05 sys + 0.00 cusr 0.00 csys = 4.67 CPU) seconds


      best regards, Rata
      (a bit surprised about the performance-differences)(btw.: ActiveState perl 5.8.8)

      Update
      As Ikegami pointed out correctly (thanks!!), the line with @arr2 is wrong. Changing it to

      map { push @arr2, ($_+ 2) } @data;

      results in

      Time taken by map block (with push) was 3 wallclock secs ( 2.33 usr 0.00 sys + 0.00 cusr 0.00 csys = 2.33 CPU) seconds

      being similar fast as the foreach ...

        that last line is buggy.
        @arr2 = map { push @arr2, ($_+ 2) } @data;
        should be
        map { push @arr2, ($_+ 2) } @data;
Re^3: Map Vs Foreach
by Marshall (Prior) on Nov 26, 2009 at 10:39 UTC
    Well....
    my @arr1; @arr1 = map { push @arr1, ($_+ 2) } @data;
    is not the way to use map to generate a new list of @data with values of +2. here is the right way...
    my @dataPlus2 = map { my $bullshit = 'XYZ'; #see below $_ + 2 }@data;
    map{} returns the value of the last statement. I put this $bullshit statement in there to "throw you off"...it means absolutely nothing!

    Use the power of the language.

    my @dataPlus2 = map { $_ + 2 }@data;
    my @roots = map { sqrt($_) }@data;

    map{} is best used for a line or two translations.

    I wouldn't normally do it this way, this is just to show you that it is possible:

    foreach my $root (map { sqrt($_) }@data) { #do something with this square root... }
      I wouldn't normally do it this way, this is just to show you that it is possible:
      foreach my $root (map { sqrt($_) }@data) { #do something with this square root... }

      Possible, but, as you doubtless know, not desirable: This version makes two passes over the list—or, rather, one pass over the list, then one pass over its transformation—whereas

      foreach my $orig ( @data ) { my $root = sqrt $orig; ... do something with square root here ... }
      does the same thing in only one pass.

      I do take issue, though, with the statement that map is best for 1- or 2-line transformations. I think that's a readability opinion, and these are always subjective. It also might lead some into using map for a short transformation to which it's not suited. I think a less subjective guideline, and one that might be more useful when deciding which to use, is:

      • Use map if we want to take in a list and output a list, and there is a 1-to-1 correspondence between input and output, however complicated that correspondence is to implement. (I know that one can use the fact that the return value from the BLOCK in map is interpreted in list context to get around this—indeed, I've done it—but I think that, if you know that, then you're past the point where general slogans will give you any guidance. :-) )
      • Use foreach for any other transformation, no matter how simple.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://809513]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (6)
As of 2014-12-22 01:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (110 votes), past polls