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.