http://www.perlmonks.org?node_id=997349


in reply to Re^3: Efficiency of map vs. more verbose basic/fundamental code
in thread Efficiency of map vs. more verbose basic/fundamental code

Edit: thanks remiah for showing me the error of my ways. While updating the benchmark test functions, I also changed the benchmark itself from 'timethese' to 'cmpthese' which displays the results in order of slowest to fastest. Using map is in fact slower than using foreach.

I realized that output should be spewing all over my console with the test right after I hit send (Doh!)

Here's my revised benchmark, with STDOUT redirected to null. Map is still 'not' the clear leader. verbose, verbose2, verbose4 and verbose4 ('for' instead of 'foreach') are all within statistical noise of each other (and can change significantly with each run), so none of them are any better than the other.

Printing to null might also have an affect on the results, but it's clear that map is 'not' faster. Maybe because for/foreach must also be ready for a 'next' or 'last' or even a 'return' within the loop? I may have to re-think when I use foreach vs map.

#!/usr/bin/perl use strict; use warnings; use Benchmark qw(:all); my %h; @h{'A'..'Z','a'..'z'} = 1..52; sub verbose { my $hash = shift; foreach my $key (sort keys %$hash) { print "$key: $hash->{$key}\n"; } } sub verbose2 { my $hash = shift; foreach (sort keys %$hash) { print "$_: $hash->{$_}\n"; } } sub verbose3 { my $hash = shift; print "$_: $hash->{$_}\n" foreach sort keys %$hash; } sub verbose4 { my $hash = shift; print "$_: $hash->{$_}\n" for sort keys %$hash; } sub idiom { my $hash = shift; print map "$_: $hash->{$_}\n", sort keys %$hash; } cmpthese(-10, { 'Verbose' => sub{ local *STDOUT; open STDOUT, '>/dev/null' or warn "Can't open /dev/null: $!"; verbose(\%h) }, 'Verbose2' => sub{ local *STDOUT; open STDOUT, '>/dev/null' or warn "Can't open /dev/null: $!"; verbose2(\%h) }, 'Verbose3' => sub{ local *STDOUT; open STDOUT, '>/dev/null' or warn "Can't open /dev/null: $!"; verbose3(\%h) }, 'Verbose4' => sub{ local *STDOUT; open STDOUT, '>/dev/null' or warn "Can't open /dev/null: $!"; verbose4(\%h) }, 'Idiom' => sub{ local *STDOUT; open STDOUT, '>/dev/null' or warn "Can't open /dev/null: $!"; idiom(\%h) }, });
Results: Rate Idiom Verbose Verbose4 Verbose3 Verbose2 Idiom 14273/s -- -9% -11% -12% -12% Verbose 15703/s 10% -- -2% -3% -3% Verbose4 16029/s 12% 2% -- -1% -1% Verbose3 16129/s 13% 3% 1% -- -0% Verbose2 16151/s 13% 3% 1% 0% --

Replies are listed 'Best First'.
Re^5: Efficiency of map vs. more verbose basic/fundamental code
by remiah (Hermit) on Oct 05, 2012 at 01:38 UTC

    "Rate" column shows how many times it could process in one second. Verbose2 is the fastest.

    "This chart is sorted from slowest to fastest ..."
    see http://search.cpan.org/~rjbs/perl-5.16.1/lib/Benchmark.pm.

    How about think of map in conjunction with lisp? Sometimes I see lisp conscious scripts at this perlmonk. For example moritz's max tree depth in this thread, or like this one, recently posted. And several times I saw the name of book 'High Order Perl', which I have not yet read...

    regards.

      Thanks for that catch remiah. ++

      I switched the benchmark methods from 'timethese' to 'cmpthese' at the same time that I fixed the test function calls, and then simply had a brain fart when I looked at the results. I've edited my post accordingly.

      Using foreach is faster than map in this example. My faith is restored (whew!).