So Marcel has been benchmarking accessor generators. He used Class::Accessor::Fast::XS which is a verbatim copy of Class::XSAccessor with the Class::Accessor interfacing code added. But he missed out on the fastest ones bar XS accessor hand-rolling. It's a combination of using Object::Tiny's constructor and Class::XSAccessor's accessor generation. (Let's call it Object::Tiny::XS!) Here's the adapted code and then the results:
Benchmarking attribute access only
#!/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 WithClassXSAccessor; use Class::XSAccessor accessors => { myattr => 'myattr' }; sub new {my $class = shift; bless {@_} => $class} package WithClassXSAccessorArray; use Class::XSAccessor::Array accessors=> { myattr => 0 }; sub new {my $class = shift; my %args = @_; bless [$args{myattr}] => $class} package WithObjectTinyXS; use Object::Tiny qw/myattr/; use Class::XSAccessor accessors => { myattr => 'myattr' }, replace => 1; 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 = {}; my $class_xsaccessor = WithClassXSAccessor->new; my $class_xsaccessor_array = WithClassXSAccessorArray->new; my $object_tiny_xs = WithObjectTinyXS->new; cmpthese(timethese(-5,{ 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}; }, object_tiny_xs => sub { $object_tiny_xs->myattr(27); my $x = $object_tiny_xs->myattr; }, class_xsaccessor => sub { $class_xsaccessor->myattr(27); my $x = $class_xsaccessor->myattr; }, class_xsaccessor_array => sub { $class_xsaccessor_array->myattr(27); my $x = $class_xsaccessor_array->myattr; }, }));
Results:
class_accessor_constructor 2454/s moose 4989/s mouse 11187/s class_methodmaker 35946/s mojo 52058/s class_accessor_complex 54325/s moose_immutable 60575/s class_accessor 75348/s class_spiffy 79642/s class_accessor_fast 89620/s class_accessor_fast_xs 107349/s spiffy 134988/s class_xsacessor_array 155608/s class_xsacessor 173799/s object_tiny 234721/s object_tiny_xs 287949/s direct_hash 449616/s
Benchmarking object creation and attribute access
#!/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 WithClassXSAccessor; use Class::XSAccessor accessors => { myattr => 'myattr' }; sub new {my $class = shift; bless {@_} => $class} package WithClassXSAccessorArray; use Class::XSAccessor::Array accessors=> { myattr => 0 }; sub new {my $class = shift; my %args = @_; bless [$args{myattr}] => $class} package WithObjectTinyXS; use Object::Tiny qw/myattr/; use Class::XSAccessor accessors => { myattr => 'myattr' }, replace => 1; package main; cmpthese(timethese(-5,{ moose => sub { my $obj = WithMoose->new(myattr => 27); my $x = $obj->myattr; }, moose_immutable => sub { my $obj = WithMooseImmutable->new(myattr => 27); my $x = $obj->myattr; }, mouse => sub { my $obj = WithMouse->new(myattr => 27); my $x = $obj->myattr; }, class_accessor => sub { my $obj = WithClassAccessor->new({ myattr => 27 }); my $x = $obj->myattr; }, class_accessor_fast => sub { my $obj = WithClassAccessorFast->new({ myattr => 27 }); my $x = $obj->myattr; }, class_accessor_fast_xs => sub { my $obj = WithClassAccessorFastXS->new({ myattr => 27 }); my $x = $obj->myattr; }, class_accessor_complex => sub { my $obj = WithClassAccessorComplex->new(myattr => 27); my $x = $obj->myattr; }, class_accessor_constructor => sub { my $obj = WithClassAccessorConstructor->new(myattr => 27); my $x = $obj->myattr; }, mojo => sub { my $obj = WithMojo->new(myattr => 27); my $x = $obj->myattr; }, class_methodmaker => sub { my $obj = WithClassMethodMaker->new(myattr => 27); my $x = $obj->myattr; }, object_tiny => sub { my $obj = WithObjectTiny->new(myattr => 27); my $x = $obj->myattr; }, spiffy => sub { my $obj = WithSpiffy->new(myattr => 27); my $x = $obj->myattr; }, class_spiffy => sub { my $obj = WithClassSpiffy->new(myattr => 27); my $x = $obj->myattr; }, direct_hash => sub { my $h = {}; $h->{myattr} = 27; my $x = $h->{myattr}; }, object_tiny_xs => sub { my $obj = WithObjectTinyXS->new(myattr => 27); my $x = $obj->myattr; }, class_xsacessor => sub { my $obj = WithClassXSAccessor->new(myattr => 27); my $x = $obj->myattr; }, class_xsacessor_array => sub { my $obj = WithClassXSAccessorArray->new(myattr => 27); my $x = $obj->myattr; }, }));
Results:
class_accessor 159366/s mojo 240146/s class_spiffy 250628/s mouse 270458/s spiffy 277170/s moose 288516/s moose_immutable 293403/s class_accessor_fast 295518/s class_accessor_constructor 302447/s accessors 318795/s class_accessor_complex 352492/s class_methodmaker 389809/s object_tiny 435876/s class_xsaccessor 537101/s class_accessor_fast_xs 572424/s class_xsaccessor_array 620285/s object_tiny_xs 638328/s direct_hash 1183721/s
I'll leave the analysis of the results to the reader.
Re:Mismatched headlines
tsee on 2008-11-03T21:31:16
Thanks. Damn tiny text boxes!