Ever since jkeenan1 started an interesting benchmarking thread a few months ago, an idea has been rattling around in the back of my head, and I've finally decided to take a stab at a solution in hopes that it would quit bugging me.

The problem is that the standard Benchmark module doesn't isolate its test cases from one another. This means that the order that cases are run in can influence the results because side effects, either obvious or obscure, can accumulate and affect later tests.

Data in global variables is an obvious source of side effects; in the below example, the grep takes longer as more items are pushed onto the array, so the test functions that run later will be reported by Benchmark as being slower:

cmpthese( 1000, { "test_1" => sub { push @global, scalar grep 1, @global }, "test_2" => sub { push @global, scalar grep 1, @global }, "test_3" => sub { push @global, scalar grep 1, @global }, } );

To address this, I created a module that overrides the normal behavior of Benchmark to run each piece of code to be timed in a separate forked process. Just use Benchmark::Forking and the above benchmark reports the "correct" conclusion that the three tests run at approximately the same speed.

Feedback would be very welcome.

package Benchmark::Forking; use strict; use Benchmark; use vars qw( $VERSION $Enabled $RunLoop ); BEGIN { $VERSION = 0.9; $Enabled = 1; $RunLoop = \&Benchmark::runloop; } sub enable { $Enabled = 1 } sub disable { $Enabled = 0 } sub enabled { $#_ ? $Enabled = $_[1] : $Enabled } sub import { enable(); goto &Benchmark::import } sub unimport { disable() } sub Benchmark::runloop { $Enabled or return &$RunLoop; open( FORK, '-|') or print join "\n", @{ &$RunLoop } and exit; my @td = <FORK>; close( FORK ) or die $!; bless \@td, 'Benchmark'; }; 1;

Update: I removed the old POD from this post, but it's still available here. An updated version is now on CPAN.)


In reply to Forking Benchmarks? by simonm

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.