File Coverage

blib/lib/Tool/Bench/Item.pm
Criterion Covered Total %
statement 19 19 100.0
branch n/a
condition n/a
subroutine 8 8 100.0
pod 3 5 60.0
total 30 32 93.7


line stmt bran cond sub pod time code
1             package Tool::Bench::Item;
2             {
3             $Tool::Bench::Item::VERSION = '0.003';
4             }
5 2     2   100185 use Mouse;
  2         35677  
  2         14  
6 2     2   632 use List::Util qw{min max sum};
  2         4  
  2         183  
7 2     2   10 use Time::HiRes qw{time};
  2         2  
  2         18  
8              
9             # ABSTRACT: A single item to be benchmarked
10              
11             =head1 SYNOPSIS
12              
13             Here you are, looking at the object for one specific item. At this level things
14             start to look much more like the unix 'time' command as this is a clock wrapped
15             around a single 'item'.
16              
17             As a matter of comparison, lets look at a simple example:
18              
19             time perl -e 'for(1..3){print $_}'
20              
21             As a Tool::Bench::Item things would look something like:
22              
23             my $item = Tool::Bench::Item->new(
24             name => 'Example',
25             code => sub{qx{perl -e 'for(1..3){print $_}'}},
26             # to be fair we call perl again to include compile time
27             );
28             $item->run;
29             printf qq{%0.3f\n} $item->times->[0];
30              
31             This is a very simple example, with very simular outcomes. But there's more
32             that an item provides, speciflcy the startup and teardown events. These are
33             untimed CodeRefs that get run before and after the core 'code'.
34              
35             Here is another set of examples comparing to 'time':
36              
37             echo 'hello' > /tmp/example && time cat /tmp/example && rm /tmp/example
38              
39             Tool::Bench::Item->new(
40             name => 'Example with startup and teardown',
41             startup => sub{qx{echo 'hello' > /tmp/example}},
42             code => sub{qx{cat /tmp/example}},
43             teardown => sub{qx{rm /tmp/example}},
44             )->run;
45              
46             In both cases we only timed 'cat' not 'echo' or 'rm'.
47              
48             =head1 ATTRIBUTES
49              
50             =head2 name
51              
52             REQUIRED.
53              
54             Stores a string name for this item.
55              
56             =cut
57              
58             has name =>
59             is => 'ro',
60             isa => 'Str',
61             required => 1,
62             ;
63              
64             =head2 code
65              
66             REQUIRED.
67              
68             A CodeRef that is to be run.
69              
70             =cut
71              
72             has code =>
73             is => 'ro',
74             isa => 'CodeRef',
75             required => 1,
76             ;
77              
78             has [qw{pre_run buildup teardown post_run}] =>
79             is => 'ro',
80             isa => 'CodeRef',
81             default => sub{sub{}},
82             ;
83              
84             has note =>
85             is => 'ro',
86             isa => 'Str',
87             default => '',
88             ;
89              
90             =head2 pre_run
91              
92             An untimed CodeRef that is executed only once before the run is 'executed'.
93              
94             =head2 buildup
95              
96             An untimed CodeRef that is executed everytime before 'run' is called.
97              
98             =head2 teardown
99              
100             An untimed CodeRef that is executed everytime after 'run' is called.
101              
102             =head2 post_run
103              
104             An untimed CodeRef that is executed only once after the run is 'executed'.
105              
106             =head2 note
107              
108             An optional string to better explain the item.
109              
110             =head2 results
111              
112             An ArrayRef that contains all the results.
113              
114             =head2 times
115              
116             An ArrayRef that contains all the times that a specific run took.
117              
118             =head2 errors
119              
120             An ArrayRef that contains all any errors that were captured.
121              
122             =cut
123              
124             has [qw{results times errors}] =>
125             is => 'rw',
126             isa => 'ArrayRef',
127             default => sub{[]},
128             ;
129              
130             =head1 METHODS
131              
132             =head2 run
133              
134             $item->run; # a single run
135             $item->run(3); # run the code 3 times
136              
137             Execute code and capture results, errors, and the time for each run.
138              
139             =cut
140              
141             before run => sub{ shift->buildup->() };
142             after run => sub{ shift->teardown->() };
143              
144             sub run {
145             my $self = shift;
146             my $loop = shift || 1;
147             for (1..$loop) {
148             local $@;
149             my $result;
150             my $start = time();
151             eval { $result = $self->code->(); };
152             my $stop = time();
153             push @{ $self->times }, $stop - $start;
154             push @{ $self->results }, $result;
155             push @{ $self->errors }, $@;
156             }
157             return $self->total_runs;
158             }
159              
160              
161             #---------------------------------------------------------------------------
162             # REPORTING HOOKS
163             #---------------------------------------------------------------------------
164             =head2 total_time
165              
166             The total time that all runs took to execute.
167              
168             =head2 min_time
169              
170             The fastest execute time.
171              
172             =head2 max_time
173              
174             The slowest execute time.
175              
176             =head2 avg_time
177              
178             The averge execute time, total_time / total_runs.
179              
180             = head2 total_runs
181              
182             The number of runs that we've captured thus far.
183              
184             =cut
185              
186 36     36 0 46 sub total_time { sum @{shift->times} }
  36         253  
187 8     8 1 12 sub min_time { min @{shift->times} }
  8         44  
188 8     8 1 10 sub max_time { max @{shift->times} }
  8         44  
189              
190             sub avg_time {
191 8     8 1 12 my $self = shift;
192 8         26 $self->total_time / $self->total_runs
193             }
194              
195 39     39 0 1492 sub total_runs { scalar(@{ shift->results }) }
  39         353  
196              
197             1;