Your test is bad. Your code strings are being evaluated inside of Benchmark, oustside of $X and $Y's scope. Right now, you're using package variables $main::X and $main::Y, which are undefined.
Proof:
use strict; use warnings; use Benchmark 'cmpthese'; my $sz = ( shift || 10 ) - 4; my $X = 'N' . 'x' x $sz . '000'; my $Y = 'N' . 'x' x $sz . '001'; cmpthese( 1, { '?!X' => 'use strict; $X =~ /^N(?!.*00$).*$/', '?!Y' => 'use strict; $Y =~ /^N(?!.*00$).*$/', '?<!X' => 'use strict; $X =~ /^N.*(?<!00$)$/', '?<!Y' => 'use strict; $Y =~ /^N.*(?<!00$)$/', } ); __END__ Benchmark: timing 1 iterations of ?!X, ?!Y, ?<!X, ?<!Y... runloop unable to compile 'use strict; $X =~ /^N(?!.*00$).*$/': Global + symbol "$X" requires explicit package name at (eval 2) line 1. code: sub { for (1 .. 1) { local $_; package main; use strict; $X =~ / +^N(?!.*00$).*$/;} }
Fix:
use strict; use warnings; use Benchmark 'cmpthese'; my $sz = ( shift || 10 ) - 4; my $X = 'N' . 'x' x $sz . '000'; my $Y = 'N' . 'x' x $sz . '001'; print '# input length: ', length( $X ), $/; cmpthese( -1, { '?!X' => sub { scalar $X =~ /^N(?!.*00$).*$/ }, '?!Y' => sub { scalar $Y =~ /^N(?!.*00$).*$/ }, '?<!X' => sub { scalar $X =~ /^N.*(?<!00$)$/ }, '?<!Y' => sub { scalar $Y =~ /^N.*(?<!00$)$/ }, } );
The scalar shouldn't make a difference as long as you don't have captures. The real difference is the sub {} instead of ''. The subs now capture over $X and $Y. Using our $X and our $Y instead of my $X and my $Y would also have done the trick.
With the fixed code, it gives me the following, even when reversed:
X = Nxxxxxx000 Y = Nxxxxxx001 Rate ?<!X ?!Y ?!X ?<!Y ?<!X 327712/s -- -39% -56% -59% ?!Y 535499/s 63% -- -29% -34% ?!X 750772/s 129% 40% -- -7% ?<!Y 805492/s 146% 50% 7% --
In reply to Re: Benchmarking instability
by ikegami
in thread Benchmarking instability
by tlm
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |