Hi! Please consider following me on twitter: @hanekomu.
2008年11月01日
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:
- Both standard and immutable Moose are quite fast.
- Mouse is still slower than Moose.
- Mojo is pretty fast in the new version 0.8.
- The standard Class::Accessor is quite slow.
Tags: Moose.
posted at: 12:58 | path: /dev | permalink | 0 comments | 0 trackbacks
Comments are closed for this story.
Trackbacks are closed for this story.