File Coverage

blib/lib/Benchmark/Confirm.pm
Criterion Covered Total %
statement 65 78 83.3
branch 15 24 62.5
condition n/a
subroutine 13 13 100.0
pod 2 3 66.6
total 95 118 80.5


line stmt bran cond sub pod time code
1             package Benchmark::Confirm;
2 9     9   17884 use strict;
  9         11  
  9         227  
3 9     9   30 use warnings;
  9         6  
  9         442  
4              
5             our $VERSION = '1.00';
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 IMPORT OPTIONS
93              
94             =head2 TAP
95              
96             If you want to get valid TAP result, you should add import option C.
97              
98             perl -MBenchmark::Confirm=TAP some_benchmark.pl
99              
100             Then you get results as valid TAP like below.
101              
102             # Benchmark: timing 1 iterations of Name1, Name2, Name3...
103             # Name1: 0 wallclock secs ( 0.00 usr + 0.00 sys = 0.00 CPU)
104             # (warning: too few iterations for a reliable count)
105             # Name2: 0 wallclock secs ( 0.00 usr + 0.00 sys = 0.00 CPU)
106             # (warning: too few iterations for a reliable count)
107             # Name3: 0 wallclock secs ( 0.00 usr + 0.00 sys = 0.00 CPU)
108             # (warning: too few iterations for a reliable count)
109             # Rate Name3 Name1 Name2
110             # Name3 10000/s -- 0% 0%
111             # Name1 10000/s 0% -- 0%
112             # Name2 10000/s 0% 0% --
113             ok 1
114             ok 2
115             ok 3
116             1..3
117              
118             =head2 no_plan
119              
120             If you want to add more tests with benchmarks, you should use import option C.
121              
122             use Benchmark::Confirm qw/no_plan timethese cmpthese/;
123              
124             my $result = timethese( 1 => +{
125             Name1 => sub { "something" },
126             Name2 => sub { "something" },
127             Name3 => sub { "something" },
128             });
129              
130             cmpthese $result;
131              
132             ok 1, 'additionaly';
133              
134             Don't worry, C invokes in C block of Benchmark::Confirm. So you don't need write that.
135              
136              
137             =head1 CAVEATS
138              
139             If benchmark code returns CODE reference, then C treats it as string value: 'CODE'. This may change in future releases.
140              
141              
142             =head1 REPOSITORY
143              
144             Benchmark::Confirm is hosted on github
145            
146              
147              
148             =head1 AUTHOR
149              
150             Dai Okabayashi Ebayashi@cpan.orgE
151              
152              
153             =head1 SEE ALSO
154              
155             L
156              
157              
158             =head1 LICENSE
159              
160             This module is free software; you can redistribute it and/or
161             modify it under the same terms as Perl itself. See L.
162              
163             =cut
164              
165 9     9   3982 use Benchmark;
  9         44769  
  9         43  
166 9     9   5084 use Test::More;
  9         92820  
  9         61  
167              
168             my $capture;
169              
170             sub import {
171 9     9   61 my $class = shift;
172              
173 9         12 my $caller = caller;
174              
175 9         74 my @imports = ($class);
176 9         19 for my $func (@_) {
177 14 50       30 next unless $func;
178 14 50       29 if ($func eq 'TAP') {
    50          
179 0         0 require IO::Capture::Stdout;
180 0         0 $capture = IO::Capture::Stdout->new;
181 0         0 $capture->start;
182             }
183             elsif ($func eq 'no_plan') {
184 9     9   2292 no strict 'refs'; ## no critic
  9         13  
  9         2242  
185 0         0 for my $f ( @Test::More::EXPORT ) {
186 0         0 *{"${caller}::$f"} = \&{"Test::More::$f"};
  0         0  
  0         0  
187             }
188             }
189             else {
190 14         25 push @imports, $func;
191             }
192             }
193 9         9576 Benchmark->export_to_level(1, @imports);
194             }
195              
196             our @CONFIRMS;
197              
198             END {
199 9 50   9   6038 if (ref $capture eq 'IO::Capture::Stdout') {
200 0         0 $capture->stop;
201 0         0 while ( my $line = $capture->read ) {
202 0         0 print "# ${line}"; # valid TAP
203             }
204             }
205 9 100       38 if (@CONFIRMS > 1) {
206 7         18 atonce();
207 7         30 Test::More::done_testing();
208             }
209             }
210              
211             sub atonce {
212 8     8 1 426 my $expect = _normalize(shift @CONFIRMS);
213 8         39 Test::More::ok(1);
214              
215 8         3230 for my $got (@CONFIRMS) {
216 16         3992 Test::More::is_deeply( _normalize($got), $expect );
217             };
218              
219 8         3496 reset_confirm();
220             }
221              
222             sub _normalize {
223 24     24   29 my $element = shift;
224 24 100       98 (ref $element eq 'CODE') ? 'CODE' : [$element];
225             }
226              
227             sub reset_confirm {
228 9     9 1 481 @CONFIRMS = ();
229             }
230              
231              
232             package # hide from PAUSE
233             Benchmark;
234 9     9   36 use strict;
  9         9  
  9         235  
235 9     9   30 no warnings 'redefine';
  9         9  
  9         2594  
236              
237             # based Benchmark 1.13
238             sub runloop {
239 60     60 0 10932 my($n, $c) = @_;
240              
241 60         89 $n+=0; # force numeric now, so garbage won't creep into the eval
242 60 50       164 croak "negative loopcount $n" if $n<0;
243 60 50       140 confess usage unless defined $c;
244 60         65 my($t0, $t1, $td); # before, after, difference
245              
246             # find package of caller so we can execute code there
247 60         240 my($curpack) = caller(0);
248 60         103 my($i, $pack)= 0;
249 60         280 while (($pack) = caller(++$i)) {
250 180 100       836 last if $pack ne $curpack;
251             }
252              
253 60         79 my ($subcode, $subref, $confirmref);
254 60 50       149 if (ref $c eq 'CODE') {
255 60         157 $subcode = "sub { for (1 .. $n) { local \$_; package $pack; &\$c; } }";
256 60         5411 $subref = eval $subcode; ## no critic
257 60         2742 $confirmref = eval "sub { package $pack; &\$c; }"; ## no critic
258             }
259             else {
260 0         0 $subcode = "sub { for (1 .. $n) { local \$_; package $pack; $c;} }";
261 0         0 $subref = _doeval($subcode);
262 0         0 $confirmref = _doeval("sub { package $pack; $c; }");
263             }
264 60 50       132 croak "runloop unable to compile '$c': $@\ncode: $subcode\n" if $@;
265 60 50       117 print STDERR "runloop $n '$subcode'\n" if $Benchmark::Debug;
266              
267 60         985 push @Benchmark::Confirm::CONFIRMS, $confirmref->();
268              
269             # Wait for the user timer to tick. This makes the error range more like
270             # -0.01, +0. If we don't wait, then it's more like -0.01, +0.01. This
271             # may not seem important, but it significantly reduces the chances of
272             # getting a too low initial $n in the initial, 'find the minimum' loop
273             # in &countit. This, in turn, can reduce the number of calls to
274             # &runloop a lot, and thus reduce additive errors.
275 60         269 my $tbase = Benchmark->new(0)->[1];
276 60         698 while ( ( $t0 = Benchmark->new(0) )->[1] == $tbase ) {} ;
277 60         560688 $subref->();
278 60         1181 $t1 = Benchmark->new($n);
279 60         477 $td = &timediff($t1, $t0);
280 60         1131 timedebug("runloop:",$td);
281 60         1187 $td;
282             }
283              
284             1;