in reply to tr faster than eq?

At first, I was confused. I ran your script as given and produced similar results. Then, I changed your benchmark slightly and got different results.
use strict; use warnings; use Benchmark qw(cmpthese); my $string = '0' x 13; cmpthese( 0, { 'eq_loop_string' => q{ for ( 0 .. 12 ) { next if ( $string eq '0000000000000' ); $_ = ( $string =~ tr/1/1/ ); } }, 'eq_loop_sub' => sub{ for ( 0 .. 12 ) { next if ( $string eq '0000000000000' ); $_ = ( $string =~ tr/1/1/ ); } }, 'tr_loop_string' => q{ for ( 0 .. 12 ) { next unless ( $_ = ( $string =~ tr/1/1/ ) ); } }, 'tr_loop_sub' => sub{ for ( 0 .. 12 ) { next unless ( $_ = ( $string =~ tr/1/1/ ) ); } }, 'eq' => q($string eq '0000000000000';), 'tr' => q($string =~ tr/1/1/;), } );
And now the results:
                    Rate eq_loop_string tr_loop_sub tr_loop_string eq_loop_sub   tr   eq
eq_loop_string  124852/s             --         -8%           -15%        -38% -97% -98%
tr_loop_sub     136139/s             9%          --            -7%        -32% -97% -98%
tr_loop_string  147082/s            18%          8%             --        -27% -97% -98%
eq_loop_sub     200481/s            61%         47%            36%          -- -95% -97%
tr             4356550/s          3389%       3100%          2862%       2073%   -- -42%
eq             7530073/s          5931%       5431%          5020%       3656%  73%   --
Is it possible that perl was having to eval the strings each time the sub was called, thus skewing the results?

thor

Feel the white light, the light within
Be your own disciple, fan the sparks of will
For all of us waiting, your kingdom will come

Replies are listed 'Best First'.
Re^2: tr faster than eq?
by ikegami (Patriarch) on Mar 10, 2005 at 18:29 UTC
    Is it possible that perl was having to eval the strings each time the sub was called, thus skewing the results?

    No, it's because they are evaluated somewhere without access to the lexical $string, so they act upon the undefined global $string. Your solution causes the test cases to be compiled where $string is still in scope.

      While what you say makes sense, why am I not getting a Use of uninitialized value in string when that code is run? warnings are turned on...that is unless it's because the eval happens in the Benchmark package and not the main package.

      thor

      Feel the white light, the light within
      Be your own disciple, fan the sparks of will
      For all of us waiting, your kingdom will come

        use warnings is block-scoped. The file is a block. Since it's being evaled in another file, your use warnings doesn't take effect.

        perl -w and $^W = 1; are scopped differently. Use these, or add use warnings inside the q(), and you'll see a gazillion warnings (one for every run).

Re^2: tr faster than eq?
by Anonymous Monk on Mar 11, 2005 at 09:23 UTC
    Is it possible that perl was having to eval the strings each time the sub was called, thus skewing the results?
    No, that's not the way how the Benchmark module works. What the module does is, once it knows how often to run the code fragments (easy if the first argument is positive, and requires some test runs if the argument is negative), it creates, as a string, a loop of the form:
    for (1 .. $n) {$code}
    where $n is the number of times to run, and $code the code you gave as an argument. And then it string evals that. There's no skewing due to re-evalling the string.

    OTOH, if you use subs as arguments, you are skewing the results, as the sub calls themselves can easily have a significant effect on the runtime of the code you want to test.