File Coverage

blib/lib/Benchmark/Confirm.pm
Criterion Covered Total %
statement 52 55 94.5
branch 11 16 68.7
condition n/a
subroutine 11 11 100.0
pod 2 3 66.6
total 76 85 89.4


line stmt bran cond sub pod time code
1             package Benchmark::Confirm;
2 9     9   27035 use strict;
  9         18  
  9         291  
3 9     9   79 use warnings;
  9         16  
  9         816  
4              
5             our $VERSION = '0.22';
6              
7             =head1 NAME
8              
9             Benchmark::Confirm - take a Benchmark and confirm returned values
10              
11              
12             =head1 SYNOPSIS
13              
14             for example, it is ordinary to execute benchmark script...
15              
16             perl some_benchmark.pl
17              
18             and use Benchmark::Confirm
19              
20             perl -MBenchmark::Confirm some_benchmark.pl
21              
22             then you get the result of benchmark and the confirmination.
23              
24             Benchmark: timing 1 iterations of Name1, Name2, Name3...
25             Name1: 0 wallclock secs ( 0.00 usr + 0.00 sys = 0.00 CPU)
26             (warning: too few iterations for a reliable count)
27             Name2: 0 wallclock secs ( 0.00 usr + 0.00 sys = 0.00 CPU)
28             (warning: too few iterations for a reliable count)
29             Name3: 0 wallclock secs ( 0.00 usr + 0.00 sys = 0.00 CPU)
30             (warning: too few iterations for a reliable count)
31             Rate Name3 Name1 Name2
32             Name3 10000/s -- 0% 0%
33             Name1 10000/s 0% -- 0%
34             Name2 10000/s 0% 0% --
35             ok 1
36             ok 2
37             ok 3
38             1..3
39              
40             See the last 4 lines, these are the result of confirmation.
41              
42              
43             =head1 DESCRIPTION
44              
45             B displays a confirmation after benchmarks that the each values from benchmark codes are equivalent or not.
46              
47             All you have to do is to use C instead of C.
48              
49             However, if you write some benchmarks in the one script, you should call some methods from C. for more details see below METHODS section.
50              
51              
52             =head1 METHODS
53              
54             See L and L sections.
55              
56             Moreover, B and B these functions are only for C.
57              
58             =head2 atonce
59              
60             C function confirms values manually.
61              
62             You can use this function when you write some benchmarks in one script. Or you shuld use C function instead on between some benchmarks.
63              
64             use strict;
65             use warnings;
66              
67             use Benchmark::Confirm qw/timethese/;
68              
69             {
70             my $result = timethese( 1 => +{
71             Name1 => sub { "something" },
72             Name2 => sub { "something" },
73             Name3 => sub { "something" },
74             });
75             }
76              
77             Benchmark::Confirm->atonce;
78              
79             {
80             my $result = timethese( 1 => +{
81             Name1 => sub { 1 },
82             Name2 => sub { 1 },
83             Name3 => sub { 1 },
84             });
85             }
86              
87             =head2 reset_confirm
88              
89             This function resets stacks of returned value.
90              
91              
92             =head1 CAVEATS
93              
94             If benchmark code returns CODE reference, then C treats it as string value: 'CODE'. This may change in future releases.
95              
96              
97             =head1 REPOSITORY
98              
99             Benchmark::Confirm is hosted on github
100            
101              
102              
103             =head1 AUTHOR
104              
105             Dai Okabayashi Ebayashi@cpan.orgE
106              
107              
108             =head1 SEE ALSO
109              
110             L
111              
112              
113             =head1 LICENSE
114              
115             This module is free software; you can redistribute it and/or
116             modify it under the same terms as Perl itself. See L.
117              
118             =cut
119              
120 9     9   20276 use Benchmark;
  9         116424  
  9         70  
121              
122             sub import {
123 9     9   16397 Benchmark->export_to_level(1, @_);
124             }
125              
126             our @CONFIRMS;
127              
128             END {
129 9 100   9   6778 if (@CONFIRMS > 1) {
130 7         33 atonce() ;
131 7         29 Test::More::done_testing();
132             }
133             }
134              
135             sub atonce {
136 8     8 1 9691 require Test::More;
137              
138 8         191194 my $expect = _normalize(shift @CONFIRMS);
139 8         46 Test::More::ok(1);
140              
141 8         6802 for my $got (@CONFIRMS) {
142 16         5528 Test::More::is_deeply( _normalize($got), $expect );
143             };
144              
145 8         11290 reset_confirm();
146             }
147              
148             sub _normalize {
149 24     24   51 my $element = shift;
150 24 100       144 (ref $element eq 'CODE') ? 'CODE' : [$element];
151             }
152              
153             sub reset_confirm {
154 9     9 1 656 @CONFIRMS = ();
155             }
156              
157              
158             package # hide from PAUSE
159             Benchmark;
160 9     9   3812 use strict;
  9         22  
  9         499  
161 9     9   87 no warnings 'redefine';
  9         15  
  9         4849  
162              
163             # based Benchmark 1.13
164             sub runloop {
165 60     60 0 13169 my($n, $c) = @_;
166              
167 60         123 $n+=0; # force numeric now, so garbage won't creep into the eval
168 60 50       231 croak "negative loopcount $n" if $n<0;
169 60 50       178 confess usage unless defined $c;
170 60         91 my($t0, $t1, $td); # before, after, difference
171              
172             # find package of caller so we can execute code there
173 60         415 my($curpack) = caller(0);
174 60         148 my($i, $pack)= 0;
175 60         450 while (($pack) = caller(++$i)) {
176 180 100       1522 last if $pack ne $curpack;
177             }
178              
179 60         99 my ($subcode, $subref, $confirmref);
180 60 50       212 if (ref $c eq 'CODE') {
181 60         214 $subcode = "sub { for (1 .. $n) { local \$_; package $pack; &\$c; } }";
182 60         9978 $subref = eval $subcode; ## no critic
183 60         4819 $confirmref = eval "sub { package $pack; &\$c; }"; ## no critic
184             }
185             else {
186 0         0 $subcode = "sub { for (1 .. $n) { local \$_; package $pack; $c;} }";
187 0         0 $subref = _doeval($subcode);
188 0         0 $confirmref = _doeval("sub { package $pack; $c; }");
189             }
190 60 50       204 croak "runloop unable to compile '$c': $@\ncode: $subcode\n" if $@;
191 60 50       159 print STDERR "runloop $n '$subcode'\n" if $Benchmark::Debug;
192              
193 60         1643 push @Benchmark::Confirm::CONFIRMS, $confirmref->();
194              
195             # Wait for the user timer to tick. This makes the error range more like
196             # -0.01, +0. If we don't wait, then it's more like -0.01, +0.01. This
197             # may not seem important, but it significantly reduces the chances of
198             # getting a too low initial $n in the initial, 'find the minimum' loop
199             # in &countit. This, in turn, can reduce the number of calls to
200             # &runloop a lot, and thus reduce additive errors.
201 60         417 my $tbase = Benchmark->new(0)->[1];
202 60         1427 while ( ( $t0 = Benchmark->new(0) )->[1] == $tbase ) {} ;
203 60         664056 $subref->();
204 60         2101 $t1 = Benchmark->new($n);
205 60         963 $td = &timediff($t1, $t0);
206 60         2264 timedebug("runloop:",$td);
207 60         1702 $td;
208             }
209              
210             1;