correct captures assignment in quote_sub
[gitmo/Moo.git] / benchmark / object_factory
CommitLineData
421104c9 1use strictures 1;
2
3use Benchmark qw/:hireswallclock cmpthese/;
4use Getopt::Long::Descriptive;
5
6use Config;
421104c9 7
8my $attrs_to_bench = {
9 plain => q|is => 'rw' |,
2c40fd5a 10 ro => q|is => 'ro' |,
11 default => q|is => 'rw', default => sub { {} } |,
421104c9 12 lazy_default => q|is => 'rw', lazy => 1, default => sub { {} } |,
13 lazy_default_qsub => q|is => 'rw', lazy => 1, default => Sub::Quote::quote_sub q{ {} } |,
14};
15
5ba2a57d 16my $cycles = {
17 1 => 'get',
18 2 => 'get/set/get',
19};
20
21my ($opts, $usage) = describe_options(
22 '%c: %o' =>
23 [ 'help|h' => 'Print usage message and exit' ],
24 [ 'bench|b:s' => 'Which benchmarks to run (all|xs|pp)', { default => 'all', regex => qr/^(?:all|xs|pp)$/ } ],
25 [ 'lib|l:s@' => 'Bench against specific lib(s), runs same benches against multiple targets, excluding non-moo benches' ],
26 [ 'attr|a:s@' => 'Which attributes to benchmark (must be defined in-file)' ],
27 [ 'cycle|c:i' => 'Which cycle to run 1 - get, 2 - get/set/get (def 1)', { default => 1 } ],
28 [ 'iterations|i:i' => 'How many iterations in each bench run (def 1000)', { default => 1000 } ],
29 [ 'totalruns|total|t:i' => 'How many times to rerun the whole benchmark (def 1)', { default => 1 } ],
30 [ 'reuse|r' => 'Reuse the object between attribute usage runs' ],
31 { getopt_conf => [qw/gnu_getopt bundling_override no_ignore_case/] },
32);
33
34$usage->die if $opts->{help};
35
36if ($opts->{attr}) {
37 my %to_bench = map { $_ => 1 } map { split /\s*,\s*/, $_ } @{$opts->{attr}};
38
39 for (keys %to_bench) {
40 die "No such attr '$_'\n" unless $attrs_to_bench->{$_};
41 }
42
43 for (keys %$attrs_to_bench) {
44 delete $attrs_to_bench->{$_} unless $to_bench{$_};
45 }
46}
47
48my @libs = map { split /\s*:\s*/, $_ } @{$opts->{lib}}
49 if ($opts->{lib});
50
51if (@libs) {
52 my $myself = $$;
53
54 for my $lib (@libs) {
55 $ENV{PERL5LIB} = join ($Config{path_sep}, $lib, @INC);
56
57 my $pid = fork();
58 die "Unable to fork: $!" unless defined $pid;
59
60 if ($pid) {
61 wait;
62 }
63 else {
64 print "Benchmarking with $lib\n";
65 last;
66 }
67 }
68
69 exit 0 if $$ == $myself;
70}
71
72require Method::Generate::Accessor; # need to pre-load for the XS shut-off to work
73
421104c9 74my $class_types;
75
76if ($opts->{bench} =~ /all|pp/) {
77 {
78 local $Method::Generate::Accessor::CAN_HAZ_XS = 0;
79 _add_moosey_has (moo => 'Moo');
80 }
81
5ba2a57d 82 _add_moosey_has (moose => 'Moose') unless @libs;
83 _add_moosey_has (mouse => 'Mousse') unless @libs;
421104c9 84}
85
86if ($opts->{bench} =~ /all|xs/) {
642c5e75 87 if (! $Method::Generate::Accessor::CAN_HAZ_XS)
421104c9 88 {
642c5e75 89 die "Requested XS benchmarks but XS isn't available in Method::Generate::Accessor";
421104c9 90 }
642c5e75 91
92 _add_moosey_has (moo_XS => 'Moo');
5ba2a57d 93 _add_moosey_has (mouse_XS => 'Mouse') unless @libs;
421104c9 94}
95
96
97# Actual Benchmarking
5ba2a57d 98for (1 .. $opts->{totalruns} ) {
421104c9 99 print "Perl $], take $_:\n";
100
101 my $objects;
102
80080483 103 for my $use_attrs (0, 1) {
104 for my $attr (keys %$attrs_to_bench) {
105 printf "\n\nBenching %s ( %s )\n====================\n",
106 $attr,
107 $use_attrs
5ba2a57d 108 ? sprintf '%s%s cycle', ($opts->{reuse} ? '' : 'new() and ' ), $cycles->{$opts->{cycle}}
80080483 109 : 'new() only'
110 ,
111 ;
112
113 cmpthese ( -1, { map {
114 my $type = $_;
115 "${type}->$attr" => sub {
116 $objects->{$type} = $class_types->{$type}->new
117 unless ( $use_attrs && $opts->{reuse} );
118
119 for (1 .. $opts->{iterations} ) {
5ba2a57d 120 if ($opts->{cycle} == 1) {
121 my $init = $objects->{$type}->$attr;
122 }
123 elsif ($opts->{cycle} == 2) {
124 my $init = $objects->{$type}->$attr;
125 $objects->{$type}->$attr('foo') unless $attr eq 'ro';
126 my $set = $objects->{$type}->$attr;
127 }
80080483 128 }
129 };
130 } keys %$class_types } );
421104c9 131 }
421104c9 132 }
5ba2a57d 133
134 print "\n\n\n";
421104c9 135}
136
137exit 0; # the end
138
139sub _add_moosey_has {
140 my ($name, $base) = @_;
141
142 my $class = "Bench::${name}";
143
144 my $perl = "package $class; use $base;";
145
146 for my $attr (keys %$attrs_to_bench) {
147 $perl .= "has $attr => ($attrs_to_bench->{$attr});";
148
149 $class_types->{$name} = $class;
150 }
151
152 $perl .= 'eval { __PACKAGE__->meta->make_immutable };';
153
154 eval $perl;
155 die $@ if $@;
156}