For Programmers: Free Programming Magazines  


Home > Archive > PERL Beginners > August 2005 > odd benchmark result, map vs foreach









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author odd benchmark result, map vs foreach
Scott R. Godin

2005-08-24, 6:56 pm

Interesting .. I would have thought that map would be faster, but it appears
that foreach is, in this instance. curious.. :)


4:52pm {193} localhost:/home/webadmin/>$ perl bench.pl
Benchmark: running Foreach, Map for at least 5 CPU seconds...
Foreach: 9 wallclock secs
( 5.24 usr + 0.00 sys = 5.24 CPU) @ 35906.30/s (n=188149)
Map: 11 wallclock secs
( 5.29 usr + 0.01 sys = 5.30 CPU) @ 24095.47/s (n=127706)
4:54pm {194} localhost:/home/webadmin/>$ cat bench.pl
#!/usr/bin/perl

use warnings;
use strict;

use Benchmark qw(timethese);

timethese( -5, {
"Foreach" => sub {
my %nr;
$nr{$_}++ foreach
qw{ shipto_company shipto_email billto_company billto_email
same_bill_ship rkh_quantity rkp_quantity rmh_quantity rmp_quantity rbh_quantity
rbp_quantity ship_on_account shipping_id_number order_number };
},
"Map" => sub {
my %nr = map {$_ => 1}
qw{ shipto_company shipto_email billto_company billto_email
same_bill_ship rkh_quantity rkp_quantity rmh_quantity rmp_quantity rbh_quantity
rbp_quantity ship_on_account shipping_id_number order_number };
}, }
);
Wiggins d'Anconia

2005-08-24, 6:56 pm

Scott R. Godin wrote:
> Interesting .. I would have thought that map would be faster, but it
> appears that foreach is, in this instance. curious.. :)
>
>
> 4:52pm {193} localhost:/home/webadmin/>$ perl bench.pl
> Benchmark: running Foreach, Map for at least 5 CPU seconds...
> Foreach: 9 wallclock secs
> ( 5.24 usr + 0.00 sys = 5.24 CPU) @ 35906.30/s (n=188149)
> Map: 11 wallclock secs
> ( 5.29 usr + 0.01 sys = 5.30 CPU) @ 24095.47/s (n=127706)
> 4:54pm {194} localhost:/home/webadmin/>$ cat bench.pl
> #!/usr/bin/perl
>
> use warnings;
> use strict;
>
> use Benchmark qw(timethese);
>
> timethese( -5, {
> "Foreach" => sub {
> my %nr;
> $nr{$_}++ foreach
> qw{ shipto_company shipto_email billto_company
> billto_email same_bill_ship rkh_quantity rkp_quantity rmh_quantity
> rmp_quantity rbh_quantity rbp_quantity ship_on_account
> shipping_id_number order_number };
> },
> "Map" => sub {
> my %nr = map {$_ => 1}
> qw{ shipto_company shipto_email billto_company
> billto_email same_bill_ship rkh_quantity rkp_quantity rmh_quantity
> rmp_quantity rbh_quantity rbp_quantity ship_on_account
> shipping_id_number order_number };
> }, }
> );
>


Your benchmark isn't controlled. In the first instance you are doing a
++ on what amounts to a scalar getting autovivified, in the second
instance you are assigning a pair of values to a list then autovivifying
it. It isn't necessarily the map vs. foreach that is causing your
difference. I think for your benchmark to be accurate you are going to
have to control the actions taken in the loop, otherwise they affect the
accuracy of your benchmark.

http://danconia.org
Wijnand Wiersma

2005-08-24, 6:56 pm

And don't run the two test too soon after eachother, your operating
system will cache some data. Also run all the tests multiple times.

Wijnand
John W. Krahn

2005-08-24, 9:55 pm

Scott R. Godin wrote:
> Interesting .. I would have thought that map would be faster, but it
> appears that foreach is, in this instance. curious.. :)
>
>
> 4:52pm {193} localhost:/home/webadmin/>$ perl bench.pl
> Benchmark: running Foreach, Map for at least 5 CPU seconds...
> Foreach: 9 wallclock secs
> ( 5.24 usr + 0.00 sys = 5.24 CPU) @ 35906.30/s (n=188149)
> Map: 11 wallclock secs
> ( 5.29 usr + 0.01 sys = 5.30 CPU) @ 24095.47/s (n=127706)
> 4:54pm {194} localhost:/home/webadmin/>$ cat bench.pl
> #!/usr/bin/perl
>
> use warnings;
> use strict;
>
> use Benchmark qw(timethese);
>
> timethese( -5, {
> "Foreach" => sub {
> my %nr;
> $nr{$_}++ foreach
> qw{ shipto_company shipto_email billto_company
> billto_email same_bill_ship rkh_quantity rkp_quantity rmh_quantity
> rmp_quantity rbh_quantity rbp_quantity ship_on_account
> shipping_id_number order_number };
> },
> "Map" => sub {
> my %nr = map {$_ => 1}
> qw{ shipto_company shipto_email billto_company
> billto_email same_bill_ship rkh_quantity rkp_quantity rmh_quantity
> rmp_quantity rbh_quantity rbp_quantity ship_on_account
> shipping_id_number order_number };
> }, }
> );


To be equivalent the foreach sub should use assignment instead of
postincrement (which is also faster.)


Foreach => sub {
my %nr;
$nr{ $_ } = 1 foreach
qw{ shipto_company shipto_email billto_company
billto_email same_bill_ship rkh_quantity rkp_quantity rmh_quantity
rmp_quantity rbh_quantity rbp_quantity ship_on_account
shipping_id_number order_number };
},


Also in my test using a hash slice is faster still.

Foreach => sub {
my %nr;
$_ = 1 foreach
@nr{ qw{ shipto_company shipto_email billto_company
billto_email same_bill_ship rkh_quantity rkp_quantity rmh_quantity
rmp_quantity rbh_quantity rbp_quantity ship_on_account
shipping_id_number order_number } };
},




John
--
use Perl;
program
fulfillment
Scott R. Godin

2005-08-26, 6:56 pm

John W. Krahn wrote:
> Scott R. Godin wrote:
>

[snip]
[color=darkred]
> To be equivalent the foreach sub should use assignment instead of
> postincrement (which is also faster.)


Interestingly, not here.

> Foreach => sub {
> my %nr;
> $nr{ $_ } = 1 foreach
> qw{ shipto_company shipto_email billto_company
> billto_email same_bill_ship rkh_quantity rkp_quantity rmh_quantity
> rmp_quantity rbh_quantity rbp_quantity ship_on_account
> shipping_id_number order_number };
> },
>
>
> Also in my test using a hash slice is faster still.


This, however, is true.

> Foreach => sub {
> my %nr;
> $_ = 1 foreach
> @nr{ qw{ shipto_company shipto_email billto_company
> billto_email same_bill_ship rkh_quantity rkp_quantity rmh_quantity
> rmp_quantity rbh_quantity rbp_quantity ship_on_account
> shipping_id_number order_number } };
> },


1:17pm {48} localhost:/home/webadmin>$ perl bench.pl
Benchmark: running Foreach, Foreach2, HashSlice, Map for at least 5 CPU seconds...
Foreach: 13 wallclock secs
( 5.32 usr + 0.02 sys = 5.34 CPU) @ 35233.90/s (n=188149)
Foreach2: 11 wallclock secs
( 5.19 usr + 0.01 sys = 5.20 CPU) @ 34134.42/s (n=177499)
HashSlice: 11 wallclock secs
( 5.18 usr + 0.00 sys = 5.18 CPU) @ 37383.20/s (n=193645)
Map: 11 wallclock secs
( 5.14 usr + 0.01 sys = 5.15 CPU) @ 23419.03/s (n=120608)
1:21pm {49} localhost:/home/webadmin>$ perl bench.pl
Benchmark: running Foreach, Foreach2, HashSlice, Map for at least 5 CPU seconds...
Foreach: 11 wallclock secs
( 5.20 usr + 0.01 sys = 5.21 CPU) @ 35404.99/s (n=184460)
Foreach2: 11 wallclock secs
( 5.20 usr + 0.01 sys = 5.21 CPU) @ 34068.91/s (n=177499)
HashSlice: 11 wallclock secs
( 5.32 usr + 0.00 sys = 5.32 CPU) @ 37099.44/s (n=197369)
Map: 11 wallclock secs
( 5.17 usr + 0.00 sys = 5.17 CPU) @ 23328.43/s (n=120608)

Maybe I'm just seeing things, but it certainly *appears* that way I originally
wrote it, is somwhat faster than the alternate 'equivalent' you offered.


1:22pm {50} localhost:/home/webadmin>$ cat bench.pl
#!/usr/bin/perl

use warnings;
use strict;

use Benchmark qw(timethese);

timethese( -5, {
"Foreach" => sub {
my %nr;
$nr{$_}++ foreach
qw{ shipto_company shipto_email billto_company billto_email
same_bill_ship rkh_quantity rkp_quantity rmh_quantity rmp_quantity rbh_quantity
rbp_quantity ship_on_account shipping_id_number order_number };
},
"Map" => sub {
my %nr = map {$_ => 1}
qw{ shipto_company shipto_email billto_company billto_email
same_bill_ship rkh_quantity rkp_quantity rmh_quantity rmp_quantity rbh_quantity
rbp_quantity ship_on_account shipping_id_number order_number };
},
"Foreach2" => sub{
my %nr;
$nr{ $_ } = 1 foreach
qw{ shipto_company shipto_email billto_company billto_email
same_bill_ship rkh_quantity rkp_quantity rmh_quantity rmp_quantity rbh_quantity
rbp_quantity ship_on_account shipping_id_number order_number };
},
"HashSlice" => sub{
my %nr;
$_ = 1 foreach
@nr{ qw{ shipto_company shipto_email billto_company billto_email
same_bill_ship rkh_quantity rkp_quantity rmh_quantity rmp_quantity rbh_quantity
rbp_quantity ship_on_account shipping_id_number order_number } };
},
});
Scott R. Godin

2005-08-26, 6:56 pm

Wiggins d'Anconia wrote:

> Your benchmark isn't controlled. In the first instance you are doing a
> ++ on what amounts to a scalar getting autovivified, in the second
> instance you are assigning a pair of values to a list then autovivifying
> it. It isn't necessarily the map vs. foreach that is causing your
> difference. I think for your benchmark to be accurate you are going to
> have to control the actions taken in the loop, otherwise they affect the
> accuracy of your benchmark.


mm this may be true, but realistically, that is how I'd write them in code I
actually use -- so it behooves me to test them the way I'd normally be using
them.. not under artificial circumstances in ways I normally wouldn't write code.

I see what you're saying and it makes sense, but in this instance I'm more
interested in seeing the results of the idiomatic expression of the end result. :)
Wiggins d'Anconia

2005-08-26, 6:56 pm

Scott R. Godin wrote:
> Wiggins d'Anconia wrote:
>
>
>
> mm this may be true, but realistically, that is how I'd write them in
> code I actually use -- so it behooves me to test them the way I'd
> normally be using them.. not under artificial circumstances in ways I
> normally wouldn't write code.
>
> I see what you're saying and it makes sense, but in this instance I'm
> more interested in seeing the results of the idiomatic expression of the
> end result. :)
>


Right, I was just being strict about your wording. You declared that the
foreach was faster than map, but strictly speaking it should have been
"the way I used foreach was faster than the way I used map", which I
wouldn't have argued with. And I am only being that strict because this
is an open, archived forum where there are plenty of people that
wouldn't have recognized the difference and may have taken you as
strictly as I did on purpose, just because they didn't know better.

As far as I am concerned write your code however you wish, make it the
fastest to read...

http://danconia.org
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com