File Coverage

blib/lib/Benchmark/Stopwatch/Pause.pm
Criterion Covered Total %
statement 73 73 100.0
branch 4 4 100.0
condition 1 3 33.3
subroutine 13 13 100.0
pod 7 7 100.0
total 98 100 98.0


line stmt bran cond sub pod time code
1 2     2   44313 use strict;
  2         5  
  2         67  
2 2     2   10 use warnings;
  2         2  
  2         77  
3             package Benchmark::Stopwatch::Pause;
4 2     2   9 use base q{Benchmark::Stopwatch};
  2         14  
  2         1804  
5             our $VERSION = '0.04';
6              
7 2     2   15167 use Time::HiRes;
  2         5  
  2         16  
8 2     2   182 use Clone 'clone';
  2         5  
  2         1092  
9              
10             =head1 NAME
11              
12             Benchmark::Stopwatch::Pause - simple timing of stages of your code with a pause option.
13              
14             =head1 VERSION
15              
16             Version 0.04
17              
18             =head1 SYNOPSIS
19              
20             #!/usr/bin/perl
21             use strict;
22             use Benchmark::Stopwatch::Pause;
23              
24             # a stopwatch to track the whole run of this script
25             my $stopwatch_whole = Benchmark::Stopwatch::Pause->new()->start;
26            
27             # a stopwatch to track just select sections of the code
28             my $stopwatch_pause = Benchmark::Stopwatch::Pause->new()->start->pause;
29              
30             sleep(5);
31              
32             foreach (1..3) {
33             $stopwatch_whole->lap('new loop ' . $_);
34             $stopwatch_pause->unpause('time code ' . $_);
35             sleep(2);
36             $stopwatch_pause->pause;
37             sleep(1);
38             }
39              
40             print $stopwatch_whole->stop->summary;
41             print "---------\n";
42             print $stopwatch_pause->stop->summary;
43              
44             # NAME TIME CUMULATIVE PERCENTAGE
45             # start 5.005 5.005 35.677%
46             # new loop 1 3.008 8.013 21.440%
47             # new loop 2 3.008 11.021 21.440%
48             # new loop 3 3.009 14.030 21.443%
49             # ---------
50             # NAME TIME CUMULATIVE PERCENTAGE
51             # start 0.000 0.000 0.000%
52             # time code 1 2.004 2.004 33.332%
53             # time code 2 2.004 4.008 33.332%
54             # time code 3 2.004 6.012 33.336%
55              
56             =head1 DESCRIPTION
57              
58             This is an extention of the handy Benchmark::Stopwatch module. This is an
59             attempt to allow very granular timeing of very specific sections of code. The
60             Stopwatch concept is carried thru in this module, while adding the ability to
61             pause your stopwatch as needed.
62              
63             =head1 CHANGES
64              
65             Things that differ from Benchmark::Stopwatch
66              
67             =over 4
68              
69             =item * Laps are now look ahead
70              
71             The concept of a lap is diffrent from Benchmark::Stopwatch, they are now look ahead.
72              
73             In Benchmark::Stopwatch :
74              
75             # ... code that is tracked by lap 'one'
76             $stopwatch->lap('one');
77              
78             In Benchmark::Stopwatch::Pause :
79              
80             $stopwatch->lap('one');
81             # ... code that is tracked by lap 'one'
82              
83             This allows the time from unpause till pause to be tied to your unpause.
84              
85             =item * _start_ is displayed in the summary
86              
87             Due to the change in the logic of what a lap is _start_ will be displayed.
88              
89             =item * _stop_ is not displayed in summary
90              
91             Due to the change in the logic of what a lap is _stop_ will always be a null event.
92              
93             =back
94              
95             =cut
96              
97             =head1 METHODS
98              
99             =head2 new
100              
101             my $stopwatch = Benchmark::Stopwatch::Pause->new;
102            
103             Creates a new stopwatch.
104              
105             =cut
106              
107             =head2 start
108              
109             $stopwatch = $stopwatch->start;
110              
111             Starts the stopwatch. Returns a reference to the stopwatch so that you can
112             chain.
113              
114             =cut
115              
116             sub start {
117 1     1 1 1542 my $self = shift;
118 1         8 $self->{start} = $self->time;
119 1         14 $self->lap('_start_');
120 1         5 return $self;
121             }
122              
123             =head2 lap
124              
125             $stopwatch = $stopwatch->lap( 'name of event' );
126              
127             Notes down the time at which an event occurs. This event will later appear in
128             the summary.
129              
130             =cut
131              
132              
133             sub lap {
134 4     4 1 7 my $self = shift;
135 4         5 my $name = shift;
136 4         10 my $time = $self->time;
137              
138             # This differs from SUPER::lap as it now tracks the pause state
139 4         21 push @{ $self->{events} }, { name => $name,
  4         18  
140             time => $time,
141             pause => $self->{pause},
142             };
143 4         21 return $self;
144             }
145              
146             =head2 pause
147              
148             $stopwatch = $stopwatch->pause;
149              
150             Notes the time at which you paused the clock, this has the effect of pausing
151             the clock. This allows you to track a small portion of repeated code without
152             worrying about any other code.
153              
154             =cut
155              
156             sub pause {
157 1     1 1 3 my $self = shift;
158 1         3 $self->{pause} = 1;
159 1         2 return $self->lap('pause');
160             }
161              
162             =head2 unpause
163              
164             $stopwatch = $stopwatch->unpause( 'name of event' );
165              
166             unpauses your stopwatch to allow for tracking again.
167              
168             =cut
169              
170             sub unpause {
171 1     1 1 2 my $self = shift;
172 1         3 my $name = shift;
173 1         2 $self->{pause} = 0;
174 1         4 return $self->lap($name)
175             }
176              
177              
178             =head2 stop
179              
180             $stopwatch = $stopwatch->stop;
181              
182             Stops the stopwatch. Returns a reference to the stopwatch so you can chain.
183              
184             =cut
185              
186             =head2 total_time
187              
188             my $time_in_seconds = $stopwatch->total_time;
189              
190             Returns the time that the stopwatch ran for in fractional seconds. If the
191             stopwatch has not been stopped yet then it returns time it has been running
192             for.
193              
194             =cut
195              
196              
197             =head2 summary
198              
199             my $summary_text = $stopwatch->summary;
200             -- or --
201             print $stopwatch->summary;
202              
203             Returns text summarizing the events that occured.
204              
205             =cut
206              
207             sub summary {
208 1     1 1 441 my $self = shift;
209 1         14 my $data = $self->as_data;
210            
211 1         3 my $header_format = "%-27.26s %-11s %-15s %s\n";
212 1         2 my $result_format = " %-27.26s %-11.3f %-15.3f %.3f%%\n";
213            
214 1         11 my $out = sprintf $header_format, qw( NAME TIME CUMULATIVE PERCENTAGE);
215              
216 1         1 foreach my $event (@{ $data->{laps} }) {
  1         3  
217 4 100       13 next if $event->{pause};
218 3         56 $out .= sprintf($result_format,
219             $event->{name},
220             $event->{elapsed_time},
221             $event->{apparent_elapse_time},
222             ($event->{elapsed_time} / $data->{total_effective_time}) * 100,
223             );
224             }
225              
226 1         9 return $out;
227             }
228              
229              
230             =head2 as_data
231              
232             my $data_structure_hashref = $stopwatch->as_data;
233              
234             Returns a data structure that contains all the information that was logged.
235             This is so that you can use this module to gather the data but then use your
236             own code to manipulate it.
237              
238             print Dumper($stopwatch_pause->stop->as_data);
239            
240             would look like:
241            
242             {
243             'total_elapsed_time' => '14.0544471740723',
244             'laps' => [
245             {
246             'pause_time' => 0,
247             'pause' => undef,
248             'apparent_elapse_time' => '1.59740447998047e-05',
249             'time' => '1179438668.5038',
250             'name' => '_start_',
251             'elapsed_time' => '1.59740447998047e-05'
252             },
253             {
254             'pause_time' => '5.00632405281067',
255             'pause' => 1,
256             'apparent_elapse_time' => '1.59740447998047e-05',
257             'time' => '1179438668.50382',
258             'name' => 'pause',
259             'elapsed_time' => '5.00632405281067'
260             },
261             {
262             'pause_time' => 0,
263             'pause' => 0,
264             'apparent_elapse_time' => '2.00797200202942',
265             'time' => '1179438673.51014',
266             'name' => 'time code 1',
267             'elapsed_time' => '2.00795602798462'
268             },
269             {
270             'pause_time' => '1.0080509185791',
271             'pause' => 1,
272             'apparent_elapse_time' => '2.00797200202942',
273             'time' => '1179438675.5181',
274             'name' => 'pause',
275             'elapsed_time' => '1.0080509185791'
276             },
277             {
278             'pause_time' => 0,
279             'pause' => 0,
280             'apparent_elapse_time' => '4.01593208312988',
281             'time' => '1179438676.52615',
282             'name' => 'time code 2',
283             'elapsed_time' => '2.00796008110046'
284             },
285             {
286             'pause_time' => '1.0080668926239',
287             'pause' => 1,
288             'apparent_elapse_time' => '4.01593208312988',
289             'time' => '1179438678.53411',
290             'name' => 'pause',
291             'elapsed_time' => '1.0080668926239'
292             },
293             {
294             'pause_time' => 0,
295             'pause' => 0,
296             'apparent_elapse_time' => '6.02388095855713',
297             'time' => '1179438679.54218',
298             'name' => 'time code 3',
299             'elapsed_time' => '2.00794887542725'
300             },
301             {
302             'pause_time' => '1.00811719894409',
303             'pause' => 1,
304             'apparent_elapse_time' => '6.02388095855713',
305             'time' => '1179438681.55012',
306             'name' => 'pause',
307             'elapsed_time' => '1.00811719894409'
308             }
309             ],
310             'stop_time' => '1179438682.55824',
311             'start_time' => '1179438668.50379',
312             'total_effective_time' => '6.0238881111145'
313             };
314             =cut
315              
316             sub as_data {
317 2     2   14 use List::Util qw{sum};
  2         4  
  2         939  
318 3     3 1 5 my $self = shift;
319 3         6 my $data = {};
320            
321 3         8 $data->{start_time} = $self->{start};
322 3   33     11 $data->{stop_time} = $self->{stop} || $self->time;
323 3         8 $data->{total_elapsed_time} = $data->{stop_time} - $data->{start_time} ;
324 3         584 $data->{laps} = [];
325              
326 3         91 my $laps = clone( $self->{events} );
327 3         13 push @$laps , { name => '_stop_', time => $data->{stop_time}};
328              
329 3         5 my $apparent_elapse_time;
330 3         9 while (scalar(@$laps) > 1 ) {
331 12         15 my $a = shift @$laps;
332 12         15 my $b = $laps->[0];
333              
334 12         23 $a->{elapsed_time} = $b->{time} - $a->{time};
335 12 100       25 $a->{pause_time} = ($a->{pause}) ? $a->{elapsed_time} : 0;
336 12         25 $apparent_elapse_time += $a->{elapsed_time} - $a->{pause_time};
337 12         30 $a->{apparent_elapse_time} = $apparent_elapse_time;
338            
339 12         13 push @{$data->{laps}},$a;
  12         36  
340             }
341            
342 3         5 $data->{total_effective_time} = $data->{total_elapsed_time} - sum( map{$_->{pause_time}} @{ $data->{laps} });
  12         37  
  3         8  
343              
344             # ~IF~ you want to have the _stop_ line then uncomment this bit...
345             #push @{$data->{laps}},{ %{$laps->[0]},
346             # pause => 0,
347             # pause_time => 0,
348             # apparent_elapse_time => $apparent_elapse_time,
349             # elapsed_time => $data->{total_effective_time},
350             # } ;
351            
352 3         14 return $data;
353             }
354              
355              
356             =head2 as_unpaused_data
357              
358             my $data_structure_hashref = $stopwatch->as_unpaused_data;
359              
360             Returns the same data structure as as_data but with out the pause laps.
361              
362             =cut
363              
364             sub as_unpaused_data {
365 1     1 1 2 my ($self) = @_;
366 1         6 my $data = $self->as_data;
367 1         3 $data->{laps} = [ grep{ ! $_->{pause} } @{ $data->{laps} } ];
  4         11  
  1         2  
368 1         6 return $data;
369             }
370              
371              
372             =head1 AUTHOR
373              
374             Ben Hengst, C<< >>
375              
376             =head1 BUGS
377              
378             Please report any bugs or feature requests to
379             C, or through the web interface at
380             L.
381             I will be notified, and then you'll automatically be notified of progress on
382             your bug as I make changes.
383              
384             =head1 SUPPORT
385              
386             You can find documentation for this module with the perldoc command.
387              
388             perldoc Benchmark::Stopwatch::Pause
389              
390             You can also look for information at:
391              
392             =over 4
393              
394             =item * AnnoCPAN: Annotated CPAN documentation
395              
396             L
397              
398             =item * CPAN Ratings
399              
400             L
401              
402             =item * RT: CPAN's request tracker
403              
404             L
405              
406             =item * Search CPAN
407              
408             L
409              
410             =back
411              
412             =head1 ACKNOWLEDGMENTS
413              
414             I couldn't have done this extention without Benchmark::Stopwatch,
415             Thanks so much Edmund von der Burg C<>
416              
417             =head1 COPYRIGHT & LICENSE
418              
419             Copyright 2007 Ben Hengst, all rights reserved.
420              
421             This program is free software; you can redistribute it and/or modify it
422             under the same terms as Perl itself.
423              
424             =cut
425              
426              
427             1;