NAME
FAST::List::Gen::Benchmark - performance tips for using FAST::List::Gen
SYNOPSIS
this document contains various benchmarks comparing the parallel syntax styles that FAST::List::Gen provides.
running the benchmark
perl -MFAST::List::Gen::Benchmark
benchmark tests
iteration:
reduce: my $x = $gen->reduce(sub {$a + $b});
# same as $gen->sum
do: my $x; $gen->do(sub {$x += $_})
for: my $x; $x += $_ for @$gen;
more/next: my $x; $gen->reset;
$x += $gen->next while $gen->more;
$gen->(): my ($x, $n); $gen->reset;
$x += $n while ($n) = $gen->();
iterator: my $it = $gen->iterator;
my ($x, $n); $gen->reset;
$x += $n while ($n) = $it->();
next: my ($x, $n); $gen->reset;
$x += $n while ($n) = $gen->next;
handle: my $x; local $_; $gen->reset;
$x += $_ while <$gen>;
benchmark results
iteration:
[+] 0 .. 10:
Rate reduce do for more/next $gen->() iterator next handle
reduce 28489/s -- -8% -30% -55% -55% -67% -68% -71%
do 31109/s 9% -- -24% -51% -51% -64% -65% -69%
for 40877/s 43% 31% -- -35% -35% -53% -55% -59%
more/next 62977/s 121% 102% 54% -- -0% -27% -30% -36%
$gen->() 63141/s 122% 103% 54% 0% -- -27% -30% -36%
iterator 86340/s 203% 178% 111% 37% 37% -- -4% -13%
next 90021/s 216% 189% 120% 43% 43% 4% -- -9%
handle 98964/s 247% 218% 142% 57% 57% 15% 10% --
[+] 0 .. 50:
Rate for $gen->() more/next reduce do next iterator handle
for 8762/s -- -40% -40% -41% -43% -59% -60% -63%
$gen->() 14546/s 66% -- -1% -2% -5% -31% -34% -38%
more/next 14646/s 67% 1% -- -2% -4% -31% -33% -38%
reduce 14892/s 70% 2% 2% -- -3% -30% -32% -37%
do 15278/s 74% 5% 4% 3% -- -28% -30% -35%
next 21222/s 142% 46% 45% 43% 39% -- -3% -10%
iterator 21892/s 150% 51% 49% 47% 43% 3% -- -7%
handle 23454/s 168% 61% 60% 57% 54% 11% 7% --
[+] 0 .. 100:
Rate for more/next $gen->() reduce do next iterator handle
for 4424/s -- -40% -42% -53% -53% -60% -61% -64%
more/next 7385/s 67% -- -3% -21% -21% -34% -34% -39%
$gen->() 7607/s 72% 3% -- -19% -19% -32% -32% -38%
reduce 9340/s 111% 26% 23% -- -0% -16% -17% -23%
do 9341/s 111% 26% 23% 0% -- -16% -17% -23%
next 11108/s 151% 50% 46% 19% 19% -- -1% -9%
iterator 11253/s 154% 52% 48% 20% 20% 1% -- -8%
handle 12190/s 176% 65% 60% 31% 31% 10% 8% --
[+] 0 .. 1000:
Rate for more/next $gen->() next iterator do reduce handle
for 446/s -- -39% -42% -61% -62% -62% -63% -64%
more/next 735/s 65% -- -4% -35% -37% -37% -39% -41%
$gen->() 763/s 71% 4% -- -33% -34% -34% -37% -38%
next 1131/s 153% 54% 48% -- -3% -3% -7% -9%
iterator 1164/s 161% 58% 52% 3% -- -0% -4% -6%
do 1165/s 161% 58% 53% 3% 0% -- -4% -6%
reduce 1210/s 171% 65% 58% 7% 4% 4% -- -2%
handle 1237/s 177% 68% 62% 9% 6% 6% 2% --
[+] 0 .. 10000:
Rate for more/next $gen->() next iterator do handle reduce
for 44.5/s -- -40% -42% -60% -62% -63% -64% -64%
more/next 74.0/s 66% -- -3% -34% -36% -39% -41% -41%
$gen->() 76.6/s 72% 4% -- -32% -34% -37% -38% -39%
next 113/s 153% 52% 47% -- -3% -8% -9% -10%
iterator 116/s 161% 57% 52% 3% -- -5% -7% -7%
do 122/s 174% 65% 59% 8% 5% -- -2% -3%
handle 124/s 179% 68% 62% 10% 7% 2% -- -1%
reduce 125/s 182% 70% 64% 11% 8% 3% 1% --
[+] 0 .. 100000:
Rate for more/next $gen->() next iterator reduce do handle
for 4.47/s -- -41% -42% -61% -62% -63% -64% -64%
more/next 7.55/s 69% -- -2% -34% -36% -38% -39% -40%
$gen->() 7.71/s 72% 2% -- -32% -35% -36% -38% -39%
next 11.4/s 155% 51% 48% -- -4% -6% -8% -9%
iterator 11.9/s 166% 57% 54% 4% -- -2% -4% -5%
reduce 12.1/s 170% 60% 57% 6% 2% -- -2% -4%
do 12.3/s 176% 64% 60% 8% 4% 2% -- -2%
handle 12.5/s 180% 66% 63% 10% 6% 4% 2% --
interpretation
once the generator size gets large enough to mask differences in initialization code, the access methods fall into 4 classes.
- 1:
for
-
while it is one of the most perlish ways to write the loop, the
$x += $_ for @$gen
construct uses a tied array, and unfortunately ties are fairly slow. all of the other constructs use the exact same underlyingFETCH
andFETCHSIZE
methods that the tied array uses, yet they are all much faster. - 2:
more/next, $gen->()
-
these are almost the same speed, and are the slowest of the non-tied access methods. the
more/next
pair results in unneeded function calls, sincenext
is checking themore
condition already. the overloaded dereference has some interpreter overhead. - 3:
next, iterator, reduce, do
-
these are the faster ways to access generators, the ranking of which depends on the size of the generator.
next
anditerator
are almost the same, and are fast across the size range.iterator
will always be slightly faster thannext
since it is the function used internally bynext
reduce
anddo
both have slower start-up time thannext
oriterator
due to a bit of initialization code. this initialization code allows for their loops to be optimized further, which letsreduce
anddo
achieve higher speeds for larger generators. - 4:
handle
-
handle iteration in a while loop is heavily optimized by perl, and is subsequently one of the fastest techniques for iterating over a generator, and this speed is independent of generator size.
in summary, stick to next, iterator, reduce, do, or handle
iteration styles if performance is a concern.
AUTHOR
Eric Strom, <asg at cpan.org>
COPYRIGHT & LICENSE
copyright 2009-2011 Eric Strom.
this program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.
see http://dev.perl.org/licenses/ for more information.