[pm-h] Performance discussion after the meeting.

G. Wade Johnson gwadej at anomaly.org
Fri Oct 10 20:37:18 PDT 2014


After the meeting last night, I decided to do some investigation of the
discussion we had about the word rotation code. I used Benchmark to get
a rough idea of the speed of the different approaches we talked about.

The four approaches I tested were:
  push    - Robert's original approach
  reanon  - recreate anonymous array each time to save memory creep
  slice   - this was the array slice assignment we looked at last
  twiddle - bit twiddling of the integer as we suggested for C

Each test runs the actual code 10_000 times so that the subroutine
overhead does not swamp the actual work. The loop overhead is probably
not much of an issue.

The program is between the lines:
----------------------------------------------------------
use strict;
use warnings;
use 5.010;

use Benchmark qw/cmpthese/;
use Devel::Size qw/total_size/;

my @word = ("\x12", "\x34", "\x56", "\x78");
my $int_word = 0x12345678;
my $iters = 10_000;

my %sizes;

print "Orig size: ", total_size( \@word ), "\n";

cmpthese( -2,
    {
        slice  => sub {
            my $w = [ @word ];
            foreach ( 0 .. $iters ) {
                @{$w}[0..3] = @{$w}[1,2,3,0];
            };
            $sizes{slice} = total_size( $w );
        }, 
        push   => sub {
            my $w = [ @word ];
            foreach ( 0 .. $iters ) {
                push @{$w}, shift @{$w};
            };
            $sizes{push} = total_size( $w );
        }, 
        reanon => sub {
            my $w = [ @word ];
            foreach ( 0 .. $iters ) {
                $w = [ @{$w}[1,2,3,0] ];
            };
            $sizes{reanon} = total_size( $w );
        }, 
        twiddle => sub {
            my $w = $int_word;
            foreach ( 0 .. $iters ) {
                $w = ($w >> 1 | $w << 3);
            }
        }, 
    }
);

foreach my $t ( sort keys %sizes )
{
    print "$t: $sizes{$t}\n"; 
}
----------------------------------------------------------

The output is below:
Orig size: 320
         Rate   slice  reanon    push twiddle
slice   127/s      --    -14%    -77%    -83%
reanon  148/s     17%      --    -74%    -81%
push    560/s    341%    278%      --    -27%
twiddle 763/s    501%    415%     36%      --
push: 400
reanon: 320
slice: 320
-----------------------------------------------------------

As you can see, Robert's solution (push) is about three times as fast
as either of the other two. (It was 5-6 times as fast on another
machine.) The memory issue I brought up has apparently been corrected.
Although the array does grow in size, it's only 80 bytes, so that would
not be a real issue.

Interestingly, the bit twiddling response is only another 36% faster in
Perl. Some of that is due to other changes in the sub. In C, I suspect
it would be a whole lot faster.

So, it looks like Robert had the best solution after all.

G. Wade
-- 
An expert is a person who has made all the mistakes that can be made in
a very narrow field.                                    -- Niels Bohr


More information about the Houston mailing list