File Coverage

blib/lib/Mojo/Util/Benchmark.pm
Criterion Covered Total %
statement 57 57 100.0
branch 4 4 100.0
condition 12 22 54.5
subroutine 13 13 100.0
pod 10 10 100.0
total 96 106 90.5


line stmt bran cond sub pod time code
1             package Mojo::Util::Benchmark;
2 13     13   1614497 use Mojo::Base -base;
  13         164658  
  13         82  
3              
4 13     13   3661 use Exporter 'import';
  13         30  
  13         533  
5 13     13   796 use Time::HiRes qw(gettimeofday);
  13         1706  
  13         113  
6              
7             our @EXPORT_OK = qw(
8             benchmark
9             );
10              
11             our $VERSION = '0.0.1';
12              
13             has 'digits' => 12; # nanoseconds
14             has 'lastTimer';
15             has 'output' => 0;
16             has 'timers' => sub { {} };
17              
18             =head2 average
19              
20             Run a callback a number of times and return the average time.
21             If no iterations are given, the default of 10 will be used.
22             If no digits are given, the default of 12 will be used.
23              
24             Returns the average time.
25              
26             =cut
27              
28             sub average {
29 3     3 1 185998 my ($self, $callback, $iterations, $digits) = @_;
30              
31 3   33     20 $digits ||= $self->digits;
32              
33 3         39 my @series = $self->series($callback, $iterations, $digits);
34              
35 3         10 my $sum = 0;
36 3         263 $sum += $_ for @series;
37              
38 3         43 return sprintf("%0.${digits}f", $sum / @series);
39             }
40              
41             =head2 benchmark
42              
43             Create a new benchmark object.
44              
45             =cut
46              
47             sub benchmark {
48 4     4 1 300190 return Mojo::Util::Benchmark->new(@_);
49             }
50              
51             =head2 microseconds
52              
53             Set the number of digits to 8.
54             Returns the object.
55              
56             =cut
57              
58             sub microseconds {
59 2     2 1 244096 my $self = shift;
60              
61 2         14 $self->digits(8);
62              
63 2         27 return $self;
64             }
65              
66             =head2 milliseconds
67              
68             Set the number of digits to 4.
69             Returns the object.
70              
71             =cut
72              
73             sub milliseconds {
74 1     1 1 169845 my $self = shift;
75              
76 1         7 $self->digits(4);
77              
78 1         16 return $self;
79             }
80              
81             =head2 nanoseconds
82              
83             Set the number of digits to 12.
84             Returns the object.
85              
86             =cut
87              
88             sub nanoseconds {
89 1     1 1 225377 my $self = shift;
90              
91 1         8 $self->digits(12);
92              
93 1         15 return $self;
94             }
95              
96             =head2 print
97              
98             Print the elapsed time for a timer.
99              
100             =cut
101              
102             sub print {
103 2     2 1 6 my ($self, $name, $digits) = @_;
104              
105 2   33     10 $digits ||= $self->timers->{$name}->{digits};
106              
107 2         6 my $duration = $self->timers->{$name}->{stop} - $self->timers->{$name}->{start};
108              
109 2         140 printf("%s: %0.${digits}f\n", $name, $duration);
110             }
111              
112             =head2 seconds
113              
114             Set the number of digits to 0.
115             Returns the object.
116              
117             =cut
118              
119             sub seconds {
120 1     1 1 219772 my $self = shift;
121              
122 1         7 $self->digits(0);
123              
124 1         51 return $self;
125             }
126              
127             =head2 series
128              
129             Run a callback a number of times and return the elapsed times.
130             If no iterations are given, the default of 10 will be used.
131             If no digits are given, the default of 12 will be used.
132              
133             Returns an array ref of elapsed times.
134              
135             =cut
136              
137             sub series {
138 5     5 1 213863 my ($self, $callback, $iterations, $digits) = @_;
139              
140 5   50     21 $iterations ||= 10;
141 5   66     23 $digits ||= $self->digits;
142              
143 5         28 my @series;
144              
145 5         38 for (1 .. $iterations) {
146 325         799 $self->start("Iteration $_");
147              
148 325         685 $callback->();
149              
150 325         936 push @series, sprintf("%0.${digits}f", $self->stop("Iteration $_"));
151             }
152              
153 5 100       106 return wantarray ? @series : \@series;
154             }
155              
156             =head2 start
157              
158             Start a timer.
159             If no name is given, the timer will be named 'elapsed'.
160             If no digits are given, the default of 4 will be used.
161              
162             Returns the object.
163              
164             =cut
165              
166             sub start {
167 333     333 1 745448 my ($self, $name, $digits) = @_;
168              
169 333   50     642 $name ||= 'elapsed';
170 333   100     970 $digits ||= $self->digits;
171              
172 333         1749 $self->lastTimer($name);
173              
174 333         1731 my $start = gettimeofday();
175              
176 333         923 $self->timers->{$self->lastTimer} = {
177             start => $start,
178             digits => $digits,
179             };
180              
181 333         2561 return $self;
182             }
183              
184             =head2 stop
185              
186             Stop a timer.
187             If no name is given, the last timer started will be stopped.
188             If no digits are given, the default of 5 will be used.
189             If output is set, the elapsed time will be printed to STDOUT.
190              
191             Returns the elapsed time.
192              
193             =cut
194              
195             sub stop {
196 333     333 1 40010 my ($self, $name, $digits) = @_;
197              
198 333   33     599 $name ||= $self->lastTimer;
199 333   66     880 $digits ||= $self->timers->{$self->lastTimer}->{digits};
200              
201 333         2162 my $end = gettimeofday();
202              
203 333         611 $self->timers->{$name}->{ stop } = $end;
204              
205 333         1229 my $duration = $self->timers->{$name}->{stop} - $self->timers->{$name}->{start};
206              
207 333 100       1865 if ($self->output) {
208 2         37 $self->print($name, $digits);
209             }
210              
211 333         2042 return $duration;
212             }
213              
214             1;