in reply to Multiplying together the numers in an array

Nice post to get myself some practice in benchmarking. Here's my try:
#!/usr/bin/perl use Benchmark qw(cmpthese); use List::Util qw(reduce); use Inline 'C'; cmpthese (-5, { 'initial' => sub { my @numbers = (2,3,4,5); my $total = 1; for(@numbers){ $total = ($total * $_); } }, 'listutil' => sub { my @numbers = (2,3,4,5); reduce{ $a*=$b } @numbers; }, 'eval' => sub { my @numbers = (2,3,4,5); eval join "*", @numbers; }, '*=' => sub { my @numbers = (2,3,4,5); my $total=1; $total *= $_ for @numbers; }, 'reducing' => sub { my @numbers = (2,3,4,5); $numbers[0] *= pop @numbers while ( @numbers > 1 ); }, 'inline' => sub { my @numbers = (2,3,4,5); multiply( \@numbers ); } }); __DATA__ __C__ double multiply (SV * terms) { I32 numterms = 0; double res = 1.0; int i; if ((!SvROK(terms)) || (SvTYPE(SvRV(terms)) != SVt_PVAV) || ((numterms = av_len((AV *)SvRV(terms))) < 0)) { return 0; } for (i = 0; i <= numterms; i++) { res *= SvNV(* av_fetch((AV *)SvRV(terms), i, 0)); } return res; }
the results:
Rate eval reducing initial *= listutil inline eval 21683/s -- -84% -84% -85% -85% -89% reducing 134819/s 522% -- -4% -6% -7% -31% initial 139854/s 545% 4% -- -3% -4% -28% *= 144019/s 564% 7% 3% -- -1% -26% listutil 145100/s 569% 8% 4% 1% -- -25% inline 194405/s 797% 44% 39% 35% 34% --
If I'm doing something wrong here, please correct me.

Replies are listed 'Best First'.
Re: Re: Multiplying together the numers in an array
by gsiems (Deacon) on Apr 09, 2004 at 12:06 UTC
    FWIW, here are a couple of variations on *= :
    #!/usr/bin/perl -w use strict; use Benchmark qw(cmpthese); cmpthese( -5, { '*=' => sub { my @numbers = (2, 3, 4, 5); my $total = 1; $total *= $_ for @numbers; }, 'pop' => sub { my @numbers = (2, 3, 4, 5); my $total = pop @numbers; $total *= $_ for @numbers; }, 'shift' => sub { my @numbers = (2, 3, 4, 5); my $total = shift @numbers; $total *= $_ for @numbers; } } );
              Rate    *=   pop shift
    *=    167004/s    --   -7%  -12%
    pop   180190/s    8%    --   -5%
    shift 188837/s   13%    5%    --
    
    
Re: Re: Multiplying together the numers in an array
by eric256 (Parson) on Apr 09, 2004 at 16:15 UTC

    This is a bit odd. I ran the sames tests because i wanted to see how a map solution measured up.

    #!/usr/bin/perl use Benchmark qw(cmpthese); use List::Util qw(reduce); cmpthese (-5, { 'initial' => sub { my @numbers = (2,3,4,5); my $total = 1; for(@numbers){ $total = ($total * $_); } }, 'listutil' => sub { my @numbers = (2,3,4,5); reduce{ $a*=$b } @numbers; }, 'eval' => sub { my @numbers = (2,3,4,5); eval join "*", @numbers; }, '*=' => sub { my @numbers = (2,3,4,5); my $total=1; $total *= $_ for @numbers; }, 'map' => sub { my @numbers = (2,3,4,5); my $total=1; map { $total *= $_ } @numbers; }, 'reducing' => sub { my @numbers = (2,3,4,5); $numbers[0] *= pop @numbers while ( @numbers > 1 ); }, });

    And got the followin results on two runs.

    C:\test>perl reduce.pl Rate eval listutil initial *= map reducin +g eval 19089/s -- -86% -90% -91% -93% -93 +% listutil 136513/s 615% -- -27% -39% -47% -51 +% initial 187039/s 880% 37% -- -16% -27% -33 +% *= 223842/s 1073% 64% 20% -- -13% -20 +% map 256001/s 1241% 88% 37% 14% -- -8 +% reducing 278189/s 1357% 104% 49% 24% 9% - +- C:\test>perl reduce.pl Rate eval listutil initial *= reducing ma +p eval 19656/s -- -87% -92% -92% -93% -94 +% listutil 150598/s 666% -- -35% -39% -47% -51 +% initial 232290/s 1082% 54% -- -6% -19% -24 +% *= 247322/s 1158% 64% 6% -- -14% -20 +% reducing 286024/s 1355% 90% 23% 16% -- -7 +% map 307455/s 1464% 104% 32% 24% 7% - +- C:\test>

    It greatly surpised me how much slower the listutil function was on my machine. Are there different implementations of it for different platforms that would cause this? Or is the small number of array elements makeing everything else meaningless?


    ___________
    Eric Hodges

      Are there different implementations of it for different platforms that would cause this?

      List::Util is implemented in two ways. One XS and one pure Perl, so it depends on your installation.

      ihb