File Coverage

blib/lib/Dumbbench/Instance.pm
Criterion Covered Total %
statement 17 49 34.6
branch 1 16 6.2
condition 0 4 0.0
subroutine 6 12 50.0
pod 5 5 100.0
total 29 86 33.7


line stmt bran cond sub pod time code
1             package Dumbbench::Instance;
2 3     3   17 use strict;
  3         6  
  3         70  
3 3     3   13 use warnings;
  3         5  
  3         54  
4 3     3   12 use Carp ();
  3         5  
  3         41  
5 3     3   11 use List::Util qw/min max/;
  3         6  
  3         344  
6              
7             require Dumbbench::Instance::Cmd;
8             require Dumbbench::Instance::PerlEval;
9             require Dumbbench::Instance::PerlSub;
10              
11             use Class::XSAccessor {
12 3         31 constructor => 'new',
13             accessors => [qw(
14             name
15             dry_result
16             result
17             )],
18             getters => [qw(timings dry_timings)],
19 3     3   21 };
  3         5  
20              
21             =encoding utf8
22              
23             =head1 NAME
24              
25             Dumbbench::Instance - A benchmark instance within a Dumbbench
26              
27             =head1 SYNOPSIS
28              
29             use Dumbbench;
30              
31             my $bench = Dumbbench->new(
32             target_rel_precision => 0.005, # seek ~0.5%
33             initial_runs => 20, # the higher the more reliable
34             );
35             $bench->add_instances(
36             Dumbbench::Instance::Cmd->new(name => 'mauve', command => [qw(perl -e 'something')]),
37             # ... more things to benchmark ...
38             );
39             $bench->run();
40             # ...
41              
42             =head1 DESCRIPTION
43              
44             This module is the base class for all benchmark instances. For example,
45             for benchmarking external commands, you should use L.
46              
47             The synopsis shows how instances of subclasses of
48             C are added to a benchmark run.
49              
50             =head1 METHODS
51              
52             =head2 new
53              
54             Constructor that takes named arguments. In this base class,
55             the only recognized argument is an instance C.
56              
57             =head2 timings
58              
59             Returns the internal array reference of timings or undef if
60             there aren't any.
61              
62             =head2 dry_timings
63              
64             Same as C but for dry-run timings.
65              
66             =head2 name
67              
68             Returns the name of the instance.
69              
70             =head2 clone
71              
72             Returns a full (deep) copy of the object. May have to be
73             augmented in subclasses.
74              
75             =cut
76              
77             sub clone {
78 0     0 1 0 my $self = shift;
79 0         0 my $clone = bless({%$self} => ref($self));
80              
81 0 0       0 if (defined $clone->dry_result) {
82 0         0 $clone->dry_result($clone->dry_result->new);
83             }
84 0 0       0 if (defined $clone->result) {
85 0         0 $clone->result($clone->result->new);
86             }
87 0         0 return $clone;
88             }
89              
90             =head2 single_run
91              
92             Needs to be implemented in subclasses:
93             A method that performs a single benchmark run and returns the
94             duration of the run in seconds.
95              
96             =cut
97              
98             sub single_run {
99 0     0 1 0 my $self = shift;
100 0         0 Carp::croak("Can't single_run Dumbbench::Instance: Choose a subclass that implements running.");
101             }
102              
103             =head2 single_dry_run
104              
105             Needs to be implemented in subclasses:
106             A method that performs a single dry-run and returns the
107             duration of the run in seconds.
108              
109             =cut
110              
111             sub single_dry_run {
112 0     0 1 0 my $self = shift;
113 0         0 Carp::croak("Can't single_dry_run Dumbbench::Instance: Choose a subclass that implements dry-running.");
114             }
115              
116             =head2 timings_as_histogram
117              
118             If the optional L module is installed,
119             C can generate histograms of the timing distributions.
120              
121             This method creates such a histogram object (of type C)
122             and returns it. If C is not available, this method
123             returns the empty list.
124              
125             =cut
126              
127             sub timings_as_histogram {
128 0     0 1 0 my $self = shift;
129 0   0     0 my $timings = $self->timings||[];
130 0         0 return $self->_timings_as_histogram($timings);
131             }
132              
133             =head2 dry_timings_as_histogram
134              
135             Same as C, but for the timings
136             from dry-runs.
137              
138             =cut
139              
140             sub dry_timings_as_histogram {
141 0     0 1 0 my $self = shift;
142 0   0     0 my $timings = $self->dry_timings||[];
143 0         0 return $self->_timings_as_histogram($timings, 'dry');
144             }
145              
146             sub _timings_as_histogram {
147 0     0   0 my $self = shift;
148 0         0 eval "require SOOT;";
149 0 0       0 return() if $@;
150              
151 0         0 my $timings = shift;
152 0         0 my $is_dry = shift;
153 0 0       0 my $min = (@$timings ? min(@$timings)*0.95 : 0);
154 0 0       0 my $max = (@$timings ? max(@$timings)*1.05 : 1);
155 0         0 my $n = max(@$timings/8, 100);
156 0 0       0 my $prefix = $is_dry ? 'dry_' : '';
157 0 0       0 my $name = defined($self->name) ? "${prefix}timings_" . $self->name : "${prefix}timings";
158 0         0 my $hist = TH1D->new($name, "distribution of benchmark ${prefix}timings", int($n), $min, $max);
159 0         0 $hist->GetXaxis()->SetTitle("run time [s]");
160 0         0 $hist->GetYaxis()->SetTitle("#");
161 0         0 $hist->Fill($_) for @$timings;
162 0         0 return $hist;
163             }
164              
165             sub _name_prefix {
166 8     8   23 my $name = $_[0]->name;
167 8 50       26 return defined($name) ? "$name: " : '';
168             }
169              
170             1;
171              
172             __END__