I found some puzzling instabilities while benchmarking a couple of alternatives that came up in a recent thread.
First the code (the only difference between before.pl and after.pl is that the definitions of $X and $Y are reversed from one to the other):
# before.pl 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' => '$X =~ /^N(?!.*00$).*$/', '?!Y' => '$Y =~ /^N(?!.*00$).*$/', '?<!X' => '$X =~ /^N.*(?<!00$)$/', '?<!Y' => '$Y =~ /^N.*(?<!00$)$/', } ); __END__ # after.pl use strict; use warnings; use Benchmark 'cmpthese'; my $sz = ( shift || 10 ) - 4; my $X = 'N' . 'x' x $sz . '001'; my $Y = 'N' . 'x' x $sz . '000'; print '# input length: ', length( $X ), $/; cmpthese( -1, { '?!X' => '$X =~ /^N(?!.*00$).*$/', '?!Y' => '$Y =~ /^N(?!.*00$).*$/', '?<!X' => '$X =~ /^N.*(?<!00$)$/', '?<!Y' => '$Y =~ /^N.*(?<!00$)$/', } ); __END__
And here's some sample output (I have seen many variations; this example only illustrates the general instability):
Note that the fastest alternative in before.pl is more than twice as fast as the fastest one in after.pl. Likewise the ratio between the fastest and the slowest in before.pl is much greater than the same ratio in after.pl.% perl before.pl 7 # input length: 7 Rate ?<!Y ?!Y ?<!X ?!X ?<!Y 1553555/s -- -70% -75% -77% ?!Y 5222982/s 236% -- -17% -22% ?<!X 6285324/s 305% 20% -- -6% ?!X 6718816/s 332% 29% 7% -- % perl after.pl # input length: 7 Rate ?<!X ?!Y ?<!Y ?!X ?<!X 2414483/s -- -1% -4% -19% ?!Y 2434774/s 1% -- -3% -18% ?<!Y 2506841/s 4% 3% -- -16% ?!X 2970871/s 23% 22% 19% --
What's going on?
the lowliest monk
In reply to Benchmarking instability by tlm
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |