Hi! Please consider following me on twitter: @hanekomu.

Dissecting the Moose Part 4 - Benchmarking Accessor Generators - Accessors Only

Update: Now uses Mojo 0.8.

Update 2: Now includes accessors and Class::MethodMaker.

Update 3: Now includes Object::Tiny, Spiffy, Class::Spiffy and direct hash access.

The previous benchmark tested mainly object construction; this benchmark performs a million get/set-operations on the same object.

As before, the benchmark was run on a 2.16 GHz MacBook with 2 GB RAM, Mac OS X 10.5.5, perl 5.8.8 (not the most recent one, I know):

Here is the program:

#!/usr/bin/env perl

use warnings;
use strict;
use Benchmark qw(cmpthese timethese :hireswallclock);


package WithMoose;
use Moose;
has myattr => ( is => 'rw' );


package WithMooseImmutable;
use Moose;
has myattr => ( is => 'rw' );
__PACKAGE__->meta->make_immutable;


package WithMouse;
use Mouse;
has myattr => ( is => 'rw' );


package WithClassAccessor;
use base qw(Class::Accessor);
__PACKAGE__->mk_accessors(qw/myattr/);


package WithClassAccessorFast;
use base qw(Class::Accessor::Fast);
__PACKAGE__->mk_accessors(qw/myattr/);


package WithClassAccessorFastXS;
use base qw(Class::Accessor::Fast::XS);
__PACKAGE__->mk_accessors(qw/myattr/);


package WithClassAccessorComplex;
use base qw(Class::Accessor::Complex);
__PACKAGE__->mk_new->mk_scalar_accessors(qw/myattr/);


package WithClassAccessorConstructor;
use base qw(Class::Accessor::Constructor Class::Accessor::Complex);
__PACKAGE__->mk_constructor->mk_scalar_accessors(qw/myattr/);


package WithMojo;
use base qw(Mojo::Base);
__PACKAGE__->attr('myattr');


package WithClassMethodMaker;
use Class::MethodMaker
    [ scalar => [ qw/myattr/ ],
      new    => [ qw/-hash new/ ],
    ];


package WithAccessors;
use accessors qw(myattr);

sub new { bless {}, shift }


package WithObjectTiny;
use Object::Tiny qw/myattr/;
sub set_myattr { $_[0]->{myattr} = $_[1] }


package WithSpiffy;
use Spiffy -base;
field 'myattr';


package WithClassSpiffy;
use Class::Spiffy -base;
field 'myattr';


package main;


my $moose                      = WithMoose->new;
my $moose_immutable            = WithMooseImmutable->new;
my $mouse                      = WithMouse->new;
my $class_accessor             = WithClassAccessor->new;
my $class_accessor_fast        = WithClassAccessorFast->new;
my $class_accessor_fast_xs     = WithClassAccessorFastXS->new;
my $class_accessor_complex     = WithClassAccessorComplex->new;
my $class_accessor_constructor = WithClassAccessorConstructor->new;
my $mojo                       = WithMojo->new;
my $class_methodmaker          = WithClassMethodMaker->new;
my $accessors                  = WithAccessors->new;
my $object_tiny                = WithObjectTiny->new;
my $spiffy                     = WithSpiffy->new;
my $class_spiffy               = WithClassSpiffy->new;
my $direct_hash                = {};

cmpthese(timethese(1_000_000,{
    moose => sub {
        $moose->myattr(27);
        my $x = $moose->myattr;
    },
    moose_immutable => sub {
        $moose_immutable->myattr(27);
        my $x = $moose_immutable->myattr;
    },
    mouse => sub {
        $mouse->myattr(27);
        my $x = $mouse->myattr;
    },
    class_accessor => sub {
        $class_accessor->myattr(27);
        my $x = $class_accessor->myattr;
    },
    class_accessor_fast => sub {
        $class_accessor_fast->myattr(27);
        my $x = $class_accessor_fast->myattr;
    },
    class_accessor_fast_xs => sub {
        $class_accessor_fast_xs->myattr(27);
        my $x = $class_accessor_fast_xs->myattr;
    },
    class_accessor_complex => sub {
        $class_accessor_complex->myattr(27);
        my $x = $class_accessor_complex->myattr;
    },
    class_accessor_constructor => sub {
        $class_accessor_constructor->myattr(27);
        my $x = $class_accessor_constructor->myattr;
    },
    mojo => sub {
        $mojo->myattr(27);
        my $x = $mojo->myattr;
    },
    class_methodmaker => sub {
        $class_methodmaker->myattr(27);
        my $x = $class_methodmaker->myattr;
    },
    accessors => sub {
        $accessors->myattr(27);
        my $x = $accessors->myattr;
    },
    object_tiny => sub {
        $object_tiny->set_myattr(27);
        my $x = $object_tiny->myattr;
    },
    spiffy => sub {
        $spiffy->myattr(27);
        my $x = $spiffy->myattr;
    },
    class_spiffy => sub {
        $class_spiffy->myattr(27);
        my $x = $class_spiffy->myattr;
    },
    direct_hash => sub {
        $direct_hash->{myattr} = 27;
        my $x = $direct_hash->{myattr};
    },
}));

To be fair, I've manually added a setter method to the Object::Tiny test class since Object::Tiny accessors only read, don't write. Here are the results:

Benchmark: timing 1000000 iterations of accessors, class_accessor, class_accessor_complex, class_accessor_constructor, class_accessor_fast, class_accessor_fast_xs, class_methodmaker, class_spiffy, direct_hash, mojo, moose, moose_immutable, mouse, object_tiny, spiffy...
 accessors: 1.9521 wallclock secs ( 1.94 usr +  0.01 sys =  1.95 CPU) @ 512820.51/s (n=1000000)
class_accessor: 4.21379 wallclock secs ( 4.18 usr +  0.02 sys =  4.20 CPU) @ 238095.24/s (n=1000000)
class_accessor_complex: 2.01732 wallclock secs ( 2.01 usr +  0.00 sys =  2.01 CPU) @ 497512.44/s (n=1000000)
class_accessor_constructor: 2.04444 wallclock secs ( 2.02 usr +  0.01 sys =  2.03 CPU) @ 492610.84/s (n=1000000)
class_accessor_fast: 2.04194 wallclock secs ( 2.01 usr +  0.01 sys =  2.02 CPU) @ 495049.50/s (n=1000000)
class_accessor_fast_xs: 0.744577 wallclock secs ( 0.74 usr +  0.01 sys =  0.75 CPU) @ 1333333.33/s (n=1000000)
class_methodmaker: 1.89544 wallclock secs ( 1.87 usr +  0.01 sys =  1.88 CPU) @ 531914.89/s (n=1000000)
class_spiffy: 2.05287 wallclock secs ( 2.05 usr +  0.01 sys =  2.06 CPU) @ 485436.89/s (n=1000000)
direct_hash: 0.405416 wallclock secs ( 0.40 usr +  0.00 sys =  0.40 CPU) @ 2500000.00/s (n=1000000)
      mojo: 1.71519 wallclock secs ( 1.70 usr + -0.01 sys =  1.69 CPU) @ 591715.98/s (n=1000000)
     moose: 1.89365 wallclock secs ( 1.87 usr +  0.01 sys =  1.88 CPU) @ 531914.89/s (n=1000000)
moose_immutable: 2.026 wallclock secs ( 2.00 usr +  0.02 sys =  2.02 CPU) @ 495049.50/s (n=1000000)
     mouse: 2.60332 wallclock secs ( 2.49 usr +  0.01 sys =  2.50 CPU) @ 400000.00/s (n=1000000)
object_tiny: 1.56868 wallclock secs ( 1.55 usr +  0.01 sys =  1.56 CPU) @ 641025.64/s (n=1000000)
    spiffy: 2.23854 wallclock secs ( 2.21 usr +  0.01 sys =  2.22 CPU) @ 450450.45/s (n=1000000)
                                Rate class_accessor mouse spiffy class_spiffy class_accessor_constructor class_accessor_fast moose_immutable class_accessor_complex accessors class_methodmaker moose mojo object_tiny class_accessor_fast_xs direct_hash
class_accessor              238095/s             --  -40%   -47%         -51%                       -52%                -52%            -52%                   -52%      -54%              -55%  -55% -60%        -63%                   -82%        -90%
mouse                       400000/s            68%    --   -11%         -18%                       -19%                -19%            -19%                   -20%      -22%              -25%  -25% -32%        -38%                   -70%        -84%
spiffy                      450450/s            89%   13%     --          -7%                        -9%                 -9%             -9%                    -9%      -12%              -15%  -15% -24%        -30%                   -66%        -82%
class_spiffy                485437/s           104%   21%     8%           --                        -1%                 -2%             -2%                    -2%       -5%               -9%   -9% -18%        -24%                   -64%        -81%
class_accessor_constructor  492611/s           107%   23%     9%           1%                         --                 -0%             -0%                    -1%       -4%               -7%   -7% -17%        -23%                   -63%        -80%
class_accessor_fast         495050/s           108%   24%    10%           2%                         0%                  --             -0%                    -0%       -3%               -7%   -7% -16%        -23%                   -63%        -80%
moose_immutable             495050/s           108%   24%    10%           2%                         0%                  0%              --                    -0%       -3%               -7%   -7% -16%        -23%                   -63%        -80%
class_accessor_complex      497512/s           109%   24%    10%           2%                         1%                  0%              0%                     --       -3%               -6%   -6% -16%        -22%                   -63%        -80%
accessors                   512821/s           115%   28%    14%           6%                         4%                  4%              4%                     3%        --               -4%   -4% -13%        -20%                   -62%        -79%
class_methodmaker           531915/s           123%   33%    18%          10%                         8%                  7%              7%                     7%        4%                --   -0% -10%        -17%                   -60%        -79%
moose                       531915/s           123%   33%    18%          10%                         8%                  7%              7%                     7%        4%                0%    -- -10%        -17%                   -60%        -79%
mojo                        591716/s           149%   48%    31%          22%                        20%                 20%             20%                    19%       15%               11%   11%   --         -8%                   -56%        -76%
object_tiny                 641026/s           169%   60%    42%          32%                        30%                 29%             29%                    29%       25%               21%   21%   8%          --                   -52%        -74%
class_accessor_fast_xs     1333333/s           460%  233%   196%         175%                       171%                169%            169%                   168%      160%              151%  151% 125%        108%                     --        -47%
direct_hash                2500000/s           950%  525%   455%         415%                       407%                405%            405%                   402%      387%              370%  370% 322%        290%                    87%          --

Some points of note:

Tags: .

Write a comment | Bookmark and Share

posted at: 12:58 | path: /dev | permalink | 0 comments | 0 trackbacks

Comments are closed for this story.

Trackbacks are closed for this story.