Profile of Benchmark.pm

← Index
NYTProf Performance Profile «line view»
For examples/benchmark4.pl
Run on Thu Aug 28 19:01:43 2014
Reported on Thu Aug 28 19:02:42 2014

Filename | /usr/share/perl/5.18/Benchmark.pm
Statements | Executed 1848261 statements in 3.83s

Subroutines
Calls | P | F | Exclusive Time | Inclusive Time | Subroutine
--- | --- | --- | --- | --- | ---
1413702 | 22 | 22 | 502ms | 502ms | Benchmark::::__ANON__[:687]Benchmark::__ANON__[:687]
106942 | 3 | 1 | 484ms | 531ms | Benchmark::::newBenchmark::new
130 | 2 | 1 | 292ms | 22.6s | Benchmark::::runloopBenchmark::runloop
106942 | 1 | 1 | 47.1ms | 47.1ms | Benchmark::::mytimeBenchmark::mytime
1 | 1 | 1 | 3.34ms | 3.57ms | Benchmark::::BEGIN@432Benchmark::BEGIN@432
1 | 1 | 1 | 2.19ms | 5.59ms | Benchmark::::BEGIN@453Benchmark::BEGIN@453
195 | 2 | 1 | 1.28ms | 1.28ms | Benchmark::::timediffBenchmark::timediff
65 | 3 | 1 | 1.22ms | 22.7s | Benchmark::::timeitBenchmark::timeit
4 | 1 | 1 | 347µs | 22.7s | Benchmark::::countitBenchmark::countit
325 | 4 | 1 | 316µs | 316µs | Benchmark::::timedebugBenchmark::timedebug
1 | 1 | 1 | 177µs | 22.7s | Benchmark::::cmptheseBenchmark::cmpthese
4 | 1 | 1 | 97µs | 22.7s | Benchmark::::timethisBenchmark::timethis
5 | 1 | 1 | 68µs | 68µs | Benchmark::::CORE:prtfBenchmark::CORE:prtf (opcode)
1 | 1 | 1 | 37µs | 22.7s | Benchmark::::timetheseBenchmark::timethese
3 | 3 | 1 | 20µs | 20µs | Benchmark::::CORE:sortBenchmark::CORE:sort (opcode)
5 | 2 | 1 | 12µs | 12µs | Benchmark::::n_to_forBenchmark::n_to_for
1 | 1 | 1 | 12µs | 24µs | Benchmark::::BEGIN@3Benchmark::BEGIN@3
4 | 1 | 1 | 10µs | 10µs | Benchmark::::cpu_aBenchmark::cpu_a
1 | 1 | 1 | 10µs | 12µs | Benchmark::::initBenchmark::init
1 | 1 | 1 | 10µs | 112µs | Benchmark::::importBenchmark::import
4 | 1 | 1 | 9µs | 9µs | Benchmark::::realBenchmark::real
1 | 1 | 1 | 8µs | 23µs | Benchmark::::BEGIN@433Benchmark::BEGIN@433
1 | 1 | 1 | 6µs | 19µs | Benchmark::::BEGIN@426Benchmark::BEGIN@426
1 | 1 | 1 | 1µs | 1µs | Benchmark::::clearallcacheBenchmark::clearallcache
1 | 1 | 1 | 1µs | 1µs | Benchmark::::disablecacheBenchmark::disablecache
0 | 0 | 0 | 0s | 0s | Benchmark::::_doevalBenchmark::_doeval
0 | 0 | 0 | 0s | 0s | Benchmark::::clearcacheBenchmark::clearcache
0 | 0 | 0 | 0s | 0s | Benchmark::::cpu_cBenchmark::cpu_c
0 | 0 | 0 | 0s | 0s | Benchmark::::cpu_pBenchmark::cpu_p
0 | 0 | 0 | 0s | 0s | Benchmark::::debugBenchmark::debug
0 | 0 | 0 | 0s | 0s | Benchmark::::enablecacheBenchmark::enablecache
0 | 0 | 0 | 0s | 0s | Benchmark::::itersBenchmark::iters
0 | 0 | 0 | 0s | 0s | Benchmark::::timestrBenchmark::timestr
0 | 0 | 0 | 0s | 0s | Benchmark::::timesumBenchmark::timesum
0 | 0 | 0 | 0s | 0s | Benchmark::::usageBenchmark::usage

Call graph for these subroutines as a Graphviz dot language file.

Line | State ments | Time on line | Calls | Time in subs | Code
--- | --- | --- | --- | --- | ---
1 |  |  |  |  | package Benchmark;
2 |  |  |  |  |
3 | 2 | 194µs | 2 | 37µs | # spent 24µs (12+13) within Benchmark::BEGIN@3 which was called: # once (12µs+13µs) by main::BEGIN@3 at line 3 use strict; # spent 24µs making 1 call to Benchmark::BEGIN@3 # spent 13µs making 1 call to strict::import
4 |  |  |  |  |
5 |  |  |  |  |
6 |  |  |  |  | =head1 NAME
7 |  |  |  |  |
8 |  |  |  |  | Benchmark - benchmark running times of Perl code
9 |  |  |  |  |
10 |  |  |  |  | =head1 SYNOPSIS
11 |  |  |  |  |
12 |  |  |  |  | use Benchmark qw(:all) ;
13 |  |  |  |  |
14 |  |  |  |  | timethis ($count, "code");
15 |  |  |  |  |
16 |  |  |  |  | # Use Perl code in strings...
17 |  |  |  |  | timethese($count, {
18 |  |  |  |  | 'Name1' => '...code1...',
19 |  |  |  |  | 'Name2' => '...code2...',
20 |  |  |  |  | });
21 |  |  |  |  |
22 |  |  |  |  | # ... or use subroutine references.
23 |  |  |  |  | timethese($count, {
24 |  |  |  |  | 'Name1' => sub { ...code1... },
25 |  |  |  |  | 'Name2' => sub { ...code2... },
26 |  |  |  |  | });
27 |  |  |  |  |
28 |  |  |  |  | # cmpthese can be used both ways as well
29 |  |  |  |  | cmpthese($count, {
30 |  |  |  |  | 'Name1' => '...code1...',
31 |  |  |  |  | 'Name2' => '...code2...',
32 |  |  |  |  | });
33 |  |  |  |  |
34 |  |  |  |  | cmpthese($count, {
35 |  |  |  |  | 'Name1' => sub { ...code1... },
36 |  |  |  |  | 'Name2' => sub { ...code2... },
37 |  |  |  |  | });
38 |  |  |  |  |
39 |  |  |  |  | # ...or in two stages
40 |  |  |  |  | $results = timethese($count,
41 |  |  |  |  | {
42 |  |  |  |  | 'Name1' => sub { ...code1... },
43 |  |  |  |  | 'Name2' => sub { ...code2... },
44 |  |  |  |  | },
45 |  |  |  |  | 'none'
46 |  |  |  |  | );
47 |  |  |  |  | cmpthese( $results ) ;
48 |  |  |  |  |
49 |  |  |  |  | $t = timeit($count, '...other code...')
50 |  |  |  |  | print "$count loops of other code took:",timestr($t),"\n";
51 |  |  |  |  |
52 |  |  |  |  | $t = countit($time, '...other code...')
53 |  |  |  |  | $count = $t->iters ;
54 |  |  |  |  | print "$count loops of other code took:",timestr($t),"\n";
55 |  |  |  |  |
56 |  |  |  |  | # enable hires wallclock timing if possible
57 |  |  |  |  | use Benchmark ':hireswallclock';
58 |  |  |  |  |
59 |  |  |  |  | =head1 DESCRIPTION
60 |  |  |  |  |
61 |  |  |  |  | The Benchmark module encapsulates a number of routines to help you
62 |  |  |  |  | figure out how long it takes to execute some code.
63 |  |  |  |  |
64 |  |  |  |  | timethis - run a chunk of code several times
65 |  |  |  |  |
66 |  |  |  |  | timethese - run several chunks of code several times
67 |  |  |  |  |
68 |  |  |  |  | cmpthese - print results of timethese as a comparison chart
69 |  |  |  |  |
70 |  |  |  |  | timeit - run a chunk of code and see how long it goes
71 |  |  |  |  |
72 |  |  |  |  | countit - see how many times a chunk of code runs in a given time
73 |  |  |  |  |
74 |  |  |  |  |
75 |  |  |  |  | =head2 Methods
76 |  |  |  |  |
77 |  |  |  |  | =over 10
78 |  |  |  |  |
79 |  |  |  |  | =item new
80 |  |  |  |  |
81 |  |  |  |  | Returns the current time. Example:
82 |  |  |  |  |
83 |  |  |  |  | use Benchmark;
84 |  |  |  |  | $t0 = Benchmark->new;
85 |  |  |  |  | # ... your code here ...
86 |  |  |  |  | $t1 = Benchmark->new;
87 |  |  |  |  | $td = timediff($t1, $t0);
88 |  |  |  |  | print "the code took:",timestr($td),"\n";
89 |  |  |  |  |
90 |  |  |  |  | =item debug
91 |  |  |  |  |
92 |  |  |  |  | Enables or disable debugging by setting the C<$Benchmark::Debug> flag:
93 |  |  |  |  |
94 |  |  |  |  | Benchmark->debug(1);
95 |  |  |  |  | $t = timeit(10, ' 5 ** $Global ');
96 |  |  |  |  | Benchmark->debug(0);
97 |  |  |  |  |
98 |  |  |  |  | =item iters
99 |  |  |  |  |
100 |  |  |  |  | Returns the number of iterations.
101 |  |  |  |  |
102 |  |  |  |  | =back
103 |  |  |  |  |
104 |  |  |  |  | =head2 Standard Exports
105 |  |  |  |  |
106 |  |  |  |  | The following routines will be exported into your namespace
107 |  |  |  |  | if you use the Benchmark module:
108 |  |  |  |  |
109 |  |  |  |  | =over 10
110 |  |  |  |  |
111 |  |  |  |  | =item timeit(COUNT, CODE)
112 |  |  |  |  |
113 |  |  |  |  | Arguments: COUNT is the number of times to run the loop, and CODE is
114 |  |  |  |  | the code to run. CODE may be either a code reference or a string to
115 |  |  |  |  | be eval'd; either way it will be run in the caller's package.
116 |  |  |  |  |
117 |  |  |  |  | Returns: a Benchmark object.
118 |  |  |  |  |
119 |  |  |  |  | =item timethis ( COUNT, CODE, [ TITLE, [ STYLE ]] )
120 |  |  |  |  |
121 |  |  |  |  | Time COUNT iterations of CODE. CODE may be a string to eval or a
122 |  |  |  |  | code reference; either way the CODE will run in the caller's package.
123 |  |  |  |  | Results will be printed to STDOUT as TITLE followed by the times.
124 |  |  |  |  | TITLE defaults to "timethis COUNT" if none is provided. STYLE
125 |  |  |  |  | determines the format of the output, as described for timestr() below.
126 |  |  |  |  |
127 |  |  |  |  | The COUNT can be zero or negative: this means the I<minimum number of
128 |  |  |  |  | CPU seconds> to run. A zero signifies the default of 3 seconds. For
129 |  |  |  |  | example to run at least for 10 seconds:
130 |  |  |  |  |
131 |  |  |  |  | timethis(-10, $code)
132 |  |  |  |  |
133 |  |  |  |  | or to run two pieces of code tests for at least 3 seconds:
134 |  |  |  |  |
135 |  |  |  |  | timethese(0, { test1 => '...', test2 => '...'})
136 |  |  |  |  |
137 |  |  |  |  | CPU seconds is, in UNIX terms, the user time plus the system time of
138 |  |  |  |  | the process itself, as opposed to the real (wallclock) time and the
139 |  |  |  |  | time spent by the child processes. Less than 0.1 seconds is not
140 |  |  |  |  | accepted (-0.01 as the count, for example, will cause a fatal runtime
141 |  |  |  |  | exception).
142 |  |  |  |  |
143 |  |  |  |  | Note that the CPU seconds is the B<minimum> time: CPU scheduling and
144 |  |  |  |  | other operating system factors may complicate the attempt so that a
145 |  |  |  |  | little bit more time is spent. The benchmark output will, however,
146 |  |  |  |  | also tell the number of C<$code> runs/second, which should be a more
147 |  |  |  |  | interesting number than the actually spent seconds.
148 |  |  |  |  |
149 |  |  |  |  | Returns a Benchmark object.
150 |  |  |  |  |
151 |  |  |  |  | =item timethese ( COUNT, CODEHASHREF, [ STYLE ] )
152 |  |  |  |  |
153 |  |  |  |  | The CODEHASHREF is a reference to a hash containing names as keys
154 |  |  |  |  | and either a string to eval or a code reference for each value.
155 |  |  |  |  | For each (KEY, VALUE) pair in the CODEHASHREF, this routine will
156 |  |  |  |  | call
157 |  |  |  |  |
158 |  |  |  |  | timethis(COUNT, VALUE, KEY, STYLE)
159 |  |  |  |  |
160 |  |  |  |  | The routines are called in string comparison order of KEY.
161 |  |  |  |  |
162 |  |  |  |  | The COUNT can be zero or negative, see timethis().
163 |  |  |  |  |
164 |  |  |  |  | Returns a hash reference of Benchmark objects, keyed by name.
165 |  |  |  |  |
166 |  |  |  |  | =item timediff ( T1, T2 )
167 |  |  |  |  |
168 |  |  |  |  | Returns the difference between two Benchmark times as a Benchmark
169 |  |  |  |  | object suitable for passing to timestr().
170 |  |  |  |  |
171 |  |  |  |  | =item timestr ( TIMEDIFF, [ STYLE, [ FORMAT ] ] )
172 |  |  |  |  |
173 |  |  |  |  | Returns a string that formats the times in the TIMEDIFF object in
174 |  |  |  |  | the requested STYLE. TIMEDIFF is expected to be a Benchmark object
175 |  |  |  |  | similar to that returned by timediff().
176 |  |  |  |  |
177 |  |  |  |  | STYLE can be any of 'all', 'none', 'noc', 'nop' or 'auto'. 'all' shows
178 |  |  |  |  | each of the 5 times available ('wallclock' time, user time, system time,
179 |  |  |  |  | user time of children, and system time of children). 'noc' shows all
180 |  |  |  |  | except the two children times. 'nop' shows only wallclock and the
181 |  |  |  |  | two children times. 'auto' (the default) will act as 'all' unless
182 |  |  |  |  | the children times are both zero, in which case it acts as 'noc'.
183 |  |  |  |  | 'none' prevents output.
184 |  |  |  |  |
185 |  |  |  |  | FORMAT is the L<printf(3)>-style format specifier (without the
186 |  |  |  |  | leading '%') to use to print the times. It defaults to '5.2f'.
187 |  |  |  |  |
188 |  |  |  |  | =back
189 |  |  |  |  |
190 |  |  |  |  | =head2 Optional Exports
191 |  |  |  |  |
192 |  |  |  |  | The following routines will be exported into your namespace
193 |  |  |  |  | if you specifically ask that they be imported:
194 |  |  |  |  |
195 |  |  |  |  | =over 10
196 |  |  |  |  |
197 |  |  |  |  | =item clearcache ( COUNT )
198 |  |  |  |  |
199 |  |  |  |  | Clear the cached time for COUNT rounds of the null loop.
200 |  |  |  |  |
201 |  |  |  |  | =item clearallcache ( )
202 |  |  |  |  |
203 |  |  |  |  | Clear all cached times.
204 |  |  |  |  |
205 |  |  |  |  | =item cmpthese ( COUNT, CODEHASHREF, [ STYLE ] )
206 |  |  |  |  |
207 |  |  |  |  | =item cmpthese ( RESULTSHASHREF, [ STYLE ] )
208 |  |  |  |  |
209 |  |  |  |  | Optionally calls timethese(), then outputs comparison chart. This:
210 |  |  |  |  |
211 |  |  |  |  | cmpthese( -1, { a => "++\$i", b => "\$i *= 2" } ) ;
212 |  |  |  |  |
213 |  |  |  |  | outputs a chart like:
214 |  |  |  |  |
215 |  |  |  |  | Rate b a
216 |  |  |  |  | b 2831802/s -- -61%
217 |  |  |  |  | a 7208959/s 155% --
218 |  |  |  |  |
219 |  |  |  |  | This chart is sorted from slowest to fastest, and shows the percent speed
220 |  |  |  |  | difference between each pair of tests.
221 |  |  |  |  |
222 |  |  |  |  | C<cmpthese> can also be passed the data structure that timethese() returns:
223 |  |  |  |  |
224 |  |  |  |  | $results = timethese( -1, { a => "++\$i", b => "\$i *= 2" } ) ;
225 |  |  |  |  | cmpthese( $results );
226 |  |  |  |  |
227 |  |  |  |  | in case you want to see both sets of results.
228 |  |  |  |  | If the first argument is an unblessed hash reference,
229 |  |  |  |  | that is RESULTSHASHREF; otherwise that is COUNT.
230 |  |  |  |  |
231 |  |  |  |  | Returns a reference to an ARRAY of rows, each row is an ARRAY of cells from the
232 |  |  |  |  | above chart, including labels. This:
233 |  |  |  |  |
234 |  |  |  |  | my $rows = cmpthese( -1, { a => '++$i', b => '$i *= 2' }, "none" );
235 |  |  |  |  |
236 |  |  |  |  | returns a data structure like:
237 |  |  |  |  |
238 |  |  |  |  | [
239 |  |  |  |  | [ '', 'Rate', 'b', 'a' ],
240 |  |  |  |  | [ 'b', '2885232/s', '--', '-59%' ],
241 |  |  |  |  | [ 'a', '7099126/s', '146%', '--' ],
242 |  |  |  |  | ]
243 |  |  |  |  |
244 |  |  |  |  | B<NOTE>: This result value differs from previous versions, which returned
245 |  |  |  |  | the C<timethese()> result structure. If you want that, just use the two
246 |  |  |  |  | statement C<timethese>...C<cmpthese> idiom shown above.
247 |  |  |  |  |
248 |  |  |  |  | Incidentally, note the variance in the result values between the two examples;
249 |  |  |  |  | this is typical of benchmarking. If this were a real benchmark, you would
250 |  |  |  |  | probably want to run a lot more iterations.
251 |  |  |  |  |
252 |  |  |  |  | =item countit(TIME, CODE)
253 |  |  |  |  |
254 |  |  |  |  | Arguments: TIME is the minimum length of time to run CODE for, and CODE is
255 |  |  |  |  | the code to run. CODE may be either a code reference or a string to
256 |  |  |  |  | be eval'd; either way it will be run in the caller's package.
257 |  |  |  |  |
258 |  |  |  |  | TIME is I<not> negative. countit() will run the loop many times to
259 |  |  |  |  | calculate the speed of CODE before running it for TIME. The actual
260 |  |  |  |  | time run for will usually be greater than TIME due to system clock
261 |  |  |  |  | resolution, so it's best to look at the number of iterations divided
262 |  |  |  |  | by the times that you are concerned with, not just the iterations.
263 |  |  |  |  |
264 |  |  |  |  | Returns: a Benchmark object.
265 |  |  |  |  |
266 |  |  |  |  | =item disablecache ( )
267 |  |  |  |  |
268 |  |  |  |  | Disable caching of timings for the null loop. This will force Benchmark
269 |  |  |  |  | to recalculate these timings for each new piece of code timed.
270 |  |  |  |  |
271 |  |  |  |  | =item enablecache ( )
272 |  |  |  |  |
273 |  |  |  |  | Enable caching of timings for the null loop. The time taken for COUNT
274 |  |  |  |  | rounds of the null loop will be calculated only once for each
275 |  |  |  |  | different COUNT used.
276 |  |  |  |  |
277 |  |  |  |  | =item timesum ( T1, T2 )
278 |  |  |  |  |
279 |  |  |  |  | Returns the sum of two Benchmark times as a Benchmark object suitable
280 |  |  |  |  | for passing to timestr().
281 |  |  |  |  |
282 |  |  |  |  | =back
283 |  |  |  |  |
284 |  |  |  |  | =head2 :hireswallclock
285 |  |  |  |  |
286 |  |  |  |  | If the Time::HiRes module has been installed, you can specify the
287 |  |  |  |  | special tag C<:hireswallclock> for Benchmark (if Time::HiRes is not
288 |  |  |  |  | available, the tag will be silently ignored). This tag will cause the
289 |  |  |  |  | wallclock time to be measured in microseconds, instead of integer
290 |  |  |  |  | seconds. Note though that the speed computations are still conducted
291 |  |  |  |  | in CPU time, not wallclock time.
292 |  |  |  |  |
293 |  |  |  |  | =head1 NOTES
294 |  |  |  |  |
295 |  |  |  |  | The data is stored as a list of values from the time and times
296 |  |  |  |  | functions:
297 |  |  |  |  |
298 |  |  |  |  | ($real, $user, $system, $children_user, $children_system, $iters)
299 |  |  |  |  |
300 |  |  |  |  | in seconds for the whole loop (not divided by the number of rounds).
301 |  |  |  |  |
302 |  |  |  |  | The timing is done using time(3) and times(3).
303 |  |  |  |  |
304 |  |  |  |  | Code is executed in the caller's package.
305 |  |  |  |  |
306 |  |  |  |  | The time of the null loop (a loop with the same
307 |  |  |  |  | number of rounds but empty loop body) is subtracted
308 |  |  |  |  | from the time of the real loop.
309 |  |  |  |  |
310 |  |  |  |  | The null loop times can be cached, the key being the
311 |  |  |  |  | number of rounds. The caching can be controlled using
312 |  |  |  |  | calls like these:
313 |  |  |  |  |
314 |  |  |  |  | clearcache($key);
315 |  |  |  |  | clearallcache();
316 |  |  |  |  |
317 |  |  |  |  | disablecache();
318 |  |  |  |  | enablecache();
319 |  |  |  |  |
320 |  |  |  |  | Caching is off by default, as it can (usually slightly) decrease
321 |  |  |  |  | accuracy and does not usually noticeably affect runtimes.
322 |  |  |  |  |
323 |  |  |  |  | =head1 EXAMPLES
324 |  |  |  |  |
325 |  |  |  |  | For example,
326 |  |  |  |  |
327 |  |  |  |  | use Benchmark qw( cmpthese ) ;
328 |  |  |  |  | $x = 3;
329 |  |  |  |  | cmpthese( -5, {
330 |  |  |  |  | a => sub{$x*$x},
331 |  |  |  |  | b => sub{$x**2},
332 |  |  |  |  | } );
333 |  |  |  |  |
334 |  |  |  |  | outputs something like this:
335 |  |  |  |  |
336 |  |  |  |  | Benchmark: running a, b, each for at least 5 CPU seconds...
337 |  |  |  |  | Rate b a
338 |  |  |  |  | b 1559428/s -- -62%
339 |  |  |  |  | a 4152037/s 166% --
340 |  |  |  |  |
341 |  |  |  |  |
342 |  |  |  |  | while
343 |  |  |  |  |
344 |  |  |  |  | use Benchmark qw( timethese cmpthese ) ;
345 |  |  |  |  | $x = 3;
346 |  |  |  |  | $r = timethese( -5, {
347 |  |  |  |  | a => sub{$x*$x},
348 |  |  |  |  | b => sub{$x**2},
349 |  |  |  |  | } );
350 |  |  |  |  | cmpthese $r;
351 |  |  |  |  |
352 |  |  |  |  | outputs something like this:
353 |  |  |  |  |
354 |  |  |  |  | Benchmark: running a, b, each for at least 5 CPU seconds...
355 |  |  |  |  | a: 10 wallclock secs ( 5.14 usr + 0.13 sys = 5.27 CPU) @ 3835055.60/s (n=20210743)
356 |  |  |  |  | b: 5 wallclock secs ( 5.41 usr + 0.00 sys = 5.41 CPU) @ 1574944.92/s (n=8520452)
357 |  |  |  |  | Rate b a
358 |  |  |  |  | b 1574945/s -- -59%
359 |  |  |  |  | a 3835056/s 144% --
360 |  |  |  |  |
361 |  |  |  |  |
362 |  |  |  |  | =head1 INHERITANCE
363 |  |  |  |  |
364 |  |  |  |  | Benchmark inherits from no other class, except of course
365 |  |  |  |  | for Exporter.
366 |  |  |  |  |
367 |  |  |  |  | =head1 CAVEATS
368 |  |  |  |  |
369 |  |  |  |  | Comparing eval'd strings with code references will give you
370 |  |  |  |  | inaccurate results: a code reference will show a slightly slower
371 |  |  |  |  | execution time than the equivalent eval'd string.
372 |  |  |  |  |
373 |  |  |  |  | The real time timing is done using time(2) and
374 |  |  |  |  | the granularity is therefore only one second.
375 |  |  |  |  |
376 |  |  |  |  | Short tests may produce negative figures because perl
377 |  |  |  |  | can appear to take longer to execute the empty loop
378 |  |  |  |  | than a short test; try:
379 |  |  |  |  |
380 |  |  |  |  | timethis(100,'1');
381 |  |  |  |  |
382 |  |  |  |  | The system time of the null loop might be slightly
383 |  |  |  |  | more than the system time of the loop with the actual
384 |  |  |  |  | code and therefore the difference might end up being E<lt> 0.
385 |  |  |  |  |
386 |  |  |  |  | =head1 SEE ALSO
387 |  |  |  |  |
388 |  |  |  |  | L<Devel::NYTProf> - a Perl code profiler
389 |  |  |  |  |
390 |  |  |  |  | =head1 AUTHORS
391 |  |  |  |  |
392 |  |  |  |  | Jarkko Hietaniemi <F<jhi@iki.fi>>, Tim Bunce <F<Tim.Bunce@ig.co.uk>>
393 |  |  |  |  |
394 |  |  |  |  | =head1 MODIFICATION HISTORY
395 |  |  |  |  |
396 |  |  |  |  | September 8th, 1994; by Tim Bunce.
397 |  |  |  |  |
398 |  |  |  |  | March 28th, 1997; by Hugo van der Sanden: added support for code
399 |  |  |  |  | references and the already documented 'debug' method; revamped
400 |  |  |  |  | documentation.
401 |  |  |  |  |
402 |  |  |  |  | April 04-07th, 1997: by Jarkko Hietaniemi, added the run-for-some-time
403 |  |  |  |  | functionality.
404 |  |  |  |  |
405 |  |  |  |  | September, 1999; by Barrie Slaymaker: math fixes and accuracy and
406 |  |  |  |  | efficiency tweaks. Added cmpthese(). A result is now returned from
407 |  |  |  |  | timethese(). Exposed countit() (was runfor()).
408 |  |  |  |  |
409 |  |  |  |  | December, 2001; by Nicholas Clark: make timestr() recognise the style 'none'
410 |  |  |  |  | and return an empty string. If cmpthese is calling timethese, make it pass the
411 |  |  |  |  | style in. (so that 'none' will suppress output). Make sub new dump its
412 |  |  |  |  | debugging output to STDERR, to be consistent with everything else.
413 |  |  |  |  | All bugs found while writing a regression test.
414 |  |  |  |  |
415 |  |  |  |  | September, 2002; by Jarkko Hietaniemi: add ':hireswallclock' special tag.
416 |  |  |  |  |
417 |  |  |  |  | February, 2004; by Chia-liang Kao: make cmpthese and timestr use time
418 |  |  |  |  | statistics for children instead of parent when the style is 'nop'.
419 |  |  |  |  |
420 |  |  |  |  | November, 2007; by Christophe Grosjean: make cmpthese and timestr compute
421 |  |  |  |  | time consistently with style argument, default is 'all' not 'noc' any more.
422 |  |  |  |  |
423 |  |  |  |  | =cut
424 |  |  |  |  |
425 |  |  |  |  | # evaluate something in a clean lexical environment
426 | 2 | 42µs | 2 | 31µs | # spent 19µs (6+12) within Benchmark::BEGIN@426 which was called: # once (6µs+12µs) by main::BEGIN@3 at line 426 sub _doeval { no strict; eval shift } # spent 19µs making 1 call to Benchmark::BEGIN@426 # spent 12µs making 1 call to strict::unimport
427 |  |  |  |  |
428 |  |  |  |  | #
429 |  |  |  |  | # put any lexicals at file scope AFTER here
430 |  |  |  |  | #
431 |  |  |  |  |
432 | 2 | 135µs | 2 | 3.61ms | # spent 3.57ms (3.34+231µs) within Benchmark::BEGIN@432 which was called: # once (3.34ms+231µs) by main::BEGIN@3 at line 432 use Carp; # spent 3.57ms making 1 call to Benchmark::BEGIN@432 # spent 38µs making 1 call to Exporter::import
433 | 2 | 128µs | 2 | 37µs | # spent 23µs (8+14) within Benchmark::BEGIN@433 which was called: # once (8µs+14µs) by main::BEGIN@3 at line 433 use Exporter; # spent 23µs making 1 call to Benchmark::BEGIN@433 # spent 14µs making 1 call to Exporter::import
434 |  |  |  |  |
435 | 1 | 500ns |  |  | our(@ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS, $VERSION);
436 |  |  |  |  |
437 | 1 | 7µs |  |  | @ISA=qw(Exporter);
438 | 1 | 1µs |  |  | @EXPORT=qw(timeit timethis timethese timediff timestr);
439 | 1 | 1µs |  |  | @EXPORT_OK=qw(timesum cmpthese countit
440 |  |  |  |  | clearcache clearallcache disablecache enablecache);
441 | 1 | 2µs |  |  | %EXPORT_TAGS=( all => [ @EXPORT, @EXPORT_OK ] ) ;
442 |  |  |  |  |
443 | 1 | 300ns |  |  | $VERSION = 1.15;
444 |  |  |  |  |
445 |  |  |  |  | # --- ':hireswallclock' special handling
446 |  |  |  |  |
447 | 1 | 100ns |  |  | my $hirestime;
448 |  |  |  |  |
449 | 106942 | 203ms |  |  | # spent 47.1ms within Benchmark::mytime which was called 106942 times, avg 441ns/call: # 106942 times (47.1ms+0s) by Benchmark::new at line 536, avg 441ns/call sub mytime () { time }
450 |  |  |  |  |
451 | 1 | 2µs | 1 | 12µs | init(); # spent 12µs making 1 call to Benchmark::init
452 |  |  |  |  |
453 |  |  |  |  | # spent 5.59ms (2.19+3.40) within Benchmark::BEGIN@453 which was called: # once (2.19ms+3.40ms) by main::BEGIN@3 at line 458 sub BEGIN {
454 | 1 | 15µs |  |  | if (eval 'require Time::HiRes') { # spent 83µs executing statements in string eval
455 | 1 | 2µs | 1 | 1.66ms | import Time::HiRes qw(time); # spent 1.66ms making 1 call to Time::HiRes::import
456 | 1 | 600ns |  |  | $hirestime = \&Time::HiRes::time;
457 |  |  |  |  | }
458 | 1 | 3.01ms | 1 | 5.59ms | } # spent 5.59ms making 1 call to Benchmark::BEGIN@453
459 |  |  |  |  |
460 |  |  |  |  | # spent 112µs (10+102) within Benchmark::import which was called: # once (10µs+102µs) by main::BEGIN@3 at line 3 of examples/benchmark4.pl sub import {
461 | 1 | 400ns |  |  | my $class = shift;
462 | 1 | 1µs |  |  | if (grep { $_ eq ":hireswallclock" } @_) {
463 |  |  |  |  | @_ = grep { $_ ne ":hireswallclock" } @_;
464 |  |  |  |  | local $^W=0;
465 |  |  |  |  | *mytime = $hirestime if defined $hirestime;
466 |  |  |  |  | }
467 | 1 | 5µs | 1 | 13µs | Benchmark->export_to_level(1, $class, @_); # spent 13µs making 1 call to Exporter::export_to_level
468 |  |  |  |  | }
469 |  |  |  |  |
470 | 1 | 200ns |  |  | our($Debug, $Min_Count, $Min_CPU, $Default_Format, $Default_Style,
471 |  |  |  |  | %_Usage, %Cache, $Do_Cache);
472 |  |  |  |  |
473 |  |  |  |  | # spent 12µs (10+2) within Benchmark::init which was called: # once (10µs+2µs) by main::BEGIN@3 at line 451 sub init {
474 | 1 | 200ns |  |  | $Debug = 0;
475 | 1 | 200ns |  |  | $Min_Count = 4;
476 | 1 | 100ns |  |  | $Min_CPU = 0.4;
477 | 1 | 300ns |  |  | $Default_Format = '5.2f';
478 | 1 | 200ns |  |  | $Default_Style = 'auto';
479 |  |  |  |  | # The cache can cause a slight loss of sys time accuracy. If a
480 |  |  |  |  | # user does many tests (>10) with *very* large counts (>10000)
481 |  |  |  |  | # or works on a very slow machine the cache may be useful.
482 | 1 | 800ns | 1 | 1µs | disablecache(); # spent 1µs making 1 call to Benchmark::disablecache
483 | 1 | 3µs | 1 | 1µs | clearallcache(); # spent 1µs making 1 call to Benchmark::clearallcache
484 |  |  |  |  | }
485 |  |  |  |  |
486 |  |  |  |  | sub debug { $Debug = ($_[1] != 0); }
487 |  |  |  |  |
488 |  |  |  |  | sub usage {
489 |  |  |  |  | my $calling_sub = (caller(1))[3];
490 |  |  |  |  | $calling_sub =~ s/^Benchmark:://;
491 |  |  |  |  | return $_Usage{$calling_sub} || '';
492 |  |  |  |  | }
493 |  |  |  |  |
494 |  |  |  |  | # The cache needs two branches: 's' for strings and 'c' for code. The
495 |  |  |  |  | # empty loop is different in these two cases.
496 |  |  |  |  |
497 | 1 | 900ns |  |  | $_Usage{clearcache} = <<'USAGE';
498 |  |  |  |  | usage: clearcache($count);
499 |  |  |  |  | USAGE
500 |  |  |  |  |
501 |  |  |  |  | sub clearcache {
502 |  |  |  |  | die usage unless @_ == 1;
503 |  |  |  |  | delete $Cache{"$_[0]c"}; delete $Cache{"$_[0]s"};
504 |  |  |  |  | }
505 |  |  |  |  |
506 | 1 | 500ns |  |  | $_Usage{clearallcache} = <<'USAGE';
507 |  |  |  |  | usage: clearallcache();
508 |  |  |  |  | USAGE
509 |  |  |  |  |
510 |  |  |  |  | # spent 1µs within Benchmark::clearallcache which was called: # once (1µs+0s) by Benchmark::init at line 483 sub clearallcache {
511 | 1 | 100ns |  |  | die usage if @_;
512 | 1 | 3µs |  |  | %Cache = ();
513 |  |  |  |  | }
514 |  |  |  |  |
515 | 1 | 300ns |  |  | $_Usage{enablecache} = <<'USAGE';
516 |  |  |  |  | usage: enablecache();
517 |  |  |  |  | USAGE
518 |  |  |  |  |
519 |  |  |  |  | sub enablecache {
520 |  |  |  |  | die usage if @_;
521 |  |  |  |  | $Do_Cache = 1;
522 |  |  |  |  | }
523 |  |  |  |  |
524 | 1 | 300ns |  |  | $_Usage{disablecache} = <<'USAGE';
525 |  |  |  |  | usage: disablecache();
526 |  |  |  |  | USAGE
527 |  |  |  |  |
528 |  |  |  |  | # spent 1µs within Benchmark::disablecache which was called: # once (1µs+0s) by Benchmark::init at line 482 sub disablecache {
529 | 1 | 200ns |  |  | die usage if @_;
530 | 1 | 5µs |  |  | $Do_Cache = 0;
531 |  |  |  |  | }
532 |  |  |  |  |
533 |  |  |  |  |
534 |  |  |  |  | # --- Functions to process the 'time' data type
535 |  |  |  |  |
536 | 106942 | 236ms | 106942 | 47.1ms | # spent 531ms (484+47.1) within Benchmark::new which was called 106942 times, avg 5µs/call: # 106682 times (482ms+46.9ms) by Benchmark::runloop at line 662, avg 5µs/call # 130 times (1.06ms+131µs) by Benchmark::runloop at line 661, avg 9µs/call # 130 times (789µs+99µs) by Benchmark::runloop at line 664, avg 7µs/call sub new { my @t = (mytime, times, @_ == 2 ? $_[1] : 0); # spent 47.1ms making 106942 calls to Benchmark::mytime, avg 441ns/call
537 | 106942 | 8.71ms |  |  | print STDERR "new=@t\n" if $Debug;
538 | 106942 | 195ms |  |  | bless \@t; }
539 |  |  |  |  |
540 |  |  |  |  | sub cpu_p { my($r,$pu,$ps,$cu,$cs) = @{$_[0]}; $pu+$ps ; }
541 |  |  |  |  | sub cpu_c { my($r,$pu,$ps,$cu,$cs) = @{$_[0]}; $cu+$cs ; }
542 | 8 | 13µs |  |  | # spent 10µs within Benchmark::cpu_a which was called 4 times, avg 3µs/call: # 4 times (10µs+0s) by Benchmark::timethis at line 839, avg 3µs/call sub cpu_a { my($r,$pu,$ps,$cu,$cs) = @{$_[0]}; $pu+$ps+$cu+$cs ; }
543 | 8 | 14µs |  |  | # spent 9µs within Benchmark::real which was called 4 times, avg 2µs/call: # 4 times (9µs+0s) by Benchmark::timethis at line 839, avg 2µs/call sub real { my($r,$pu,$ps,$cu,$cs) = @{$_[0]}; $r ; }
544 |  |  |  |  | sub iters { $_[0]->[5] ; }
545 |  |  |  |  |
546 |  |  |  |  |
547 | 1 | 300ns |  |  | $_Usage{timediff} = <<'USAGE';
548 |  |  |  |  | usage: $result_diff = timediff($result1, $result2);
549 |  |  |  |  | USAGE
550 |  |  |  |  |
551 |  |  |  |  | # spent 1.28ms within Benchmark::timediff which was called 195 times, avg 7µs/call: # 130 times (963µs+0s) by Benchmark::runloop at line 665, avg 7µs/call # 65 times (321µs+0s) by Benchmark::timeit at line 696, avg 5µs/call sub timediff {
552 | 195 | 64µs |  |  | my($a, $b) = @_;
553 |  |  |  |  |
554 | 195 | 97µs |  |  | die usage unless ref $a and ref $b;
555 |  |  |  |  |
556 | 195 | 27µs |  |  | my @r;
557 | 195 | 870µs |  |  | for (my $i=0; $i < @$a; ++$i) {
558 |  |  |  |  | push(@r, $a->[$i] - $b->[$i]);
559 |  |  |  |  | }
560 |  |  |  |  | #die "Bad timediff(): ($r[1] + $r[2]) <= 0 (@$a[1,2]|@$b[1,2])\n"
561 |  |  |  |  | # if ($r[1] + $r[2]) < 0;
562 | 195 | 386µs |  |  | bless \@r;
563 |  |  |  |  | }
564 |  |  |  |  |
565 | 1 | 300ns |  |  | $_Usage{timesum} = <<'USAGE';
566 |  |  |  |  | usage: $sum = timesum($result1, $result2);
567 |  |  |  |  | USAGE
568 |  |  |  |  |
569 |  |  |  |  | sub timesum {
570 |  |  |  |  | my($a, $b) = @_;
571 |  |  |  |  |
572 |  |  |  |  | die usage unless ref $a and ref $b;
573 |  |  |  |  |
574 |  |  |  |  | my @r;
575 |  |  |  |  | for (my $i=0; $i < @$a; ++$i) {
576 |  |  |  |  | push(@r, $a->[$i] + $b->[$i]);
577 |  |  |  |  | }
578 |  |  |  |  | bless \@r;
579 |  |  |  |  | }
580 |  |  |  |  |
581 |  |  |  |  |
582 | 1 | 300ns |  |  | $_Usage{timestr} = <<'USAGE';
583 |  |  |  |  | usage: $formatted_result = timestr($result1);
584 |  |  |  |  | USAGE
585 |  |  |  |  |
586 |  |  |  |  | sub timestr {
587 |  |  |  |  | my($tr, $style, $f) = @_;
588 |  |  |  |  |
589 |  |  |  |  | die usage unless ref $tr;
590 |  |  |  |  |
591 |  |  |  |  | my @t = @$tr;
592 |  |  |  |  | warn "bad time value (@t)" unless @t==6;
593 |  |  |  |  | my($r, $pu, $ps, $cu, $cs, $n) = @t;
594 |  |  |  |  | my($pt, $ct, $tt) = ($tr->cpu_p, $tr->cpu_c, $tr->cpu_a);
595 |  |  |  |  | $f = $Default_Format unless defined $f;
596 |  |  |  |  | # format a time in the required style, other formats may be added here
597 |  |  |  |  | $style ||= $Default_Style;
598 |  |  |  |  | return '' if $style eq 'none';
599 |  |  |  |  | $style = ($ct>0) ? 'all' : 'noc' if $style eq 'auto';
600 |  |  |  |  | my $s = "@t $style"; # default for unknown style
601 |  |  |  |  | my $w = $hirestime ? "%2g" : "%2d";
602 |  |  |  |  | $s = sprintf("$w wallclock secs (%$f usr %$f sys + %$f cusr %$f csys = %$f CPU)",
603 |  |  |  |  | $r,$pu,$ps,$cu,$cs,$tt) if $style eq 'all';
604 |  |  |  |  | $s = sprintf("$w wallclock secs (%$f usr + %$f sys = %$f CPU)",
605 |  |  |  |  | $r,$pu,$ps,$pt) if $style eq 'noc';
606 |  |  |  |  | $s = sprintf("$w wallclock secs (%$f cusr + %$f csys = %$f CPU)",
607 |  |  |  |  | $r,$cu,$cs,$ct) if $style eq 'nop';
608 |  |  |  |  | my $elapsed = do {
609 |  |  |  |  | if ($style eq 'nop') {$cu+$cs}
610 |  |  |  |  | elsif ($style eq 'noc') {$pu+$ps}
611 |  |  |  |  | else {$cu+$cs+$pu+$ps}
612 |  |  |  |  | };
613 |  |  |  |  | $s .= sprintf(" @ %$f/s (n=$n)",$n/($elapsed)) if $n && $elapsed;
614 |  |  |  |  | $s;
615 |  |  |  |  | }
616 |  |  |  |  |
617 |  |  |  |  | # spent 316µs within Benchmark::timedebug which was called 325 times, avg 973ns/call: # 130 times (168µs+0s) by Benchmark::runloop at line 666, avg 1µs/call # 65 times (58µs+0s) by Benchmark::timeit at line 697, avg 894ns/call # 65 times (47µs+0s) by Benchmark::timeit at line 698, avg 729ns/call # 65 times (43µs+0s) by Benchmark::timeit at line 699, avg 658ns/call sub timedebug {
618 | 325 | 97µs |  |  | my($msg, $t) = @_;
619 | 325 | 2.98ms |  |  | print STDERR "$msg",timestr($t),"\n" if $Debug;
620 |  |  |  |  | }
621 |  |  |  |  |
622 |  |  |  |  | # --- Functions implementing low-level support for timing loops
623 |  |  |  |  |
624 | 1 | 600ns |  |  | $_Usage{runloop} = <<'USAGE';
625 |  |  |  |  | usage: runloop($number, [$string | $coderef])
626 |  |  |  |  | USAGE
627 |  |  |  |  |
628 |  |  |  |  | # spent 22.6s (292ms+22.4) within Benchmark::runloop which was called 130 times, avg 174ms/call: # 65 times (144ms+18.0s) by Benchmark::timeit at line 694, avg 279ms/call # 65 times (148ms+4.38s) by Benchmark::timeit at line 687, avg 69.7ms/call sub runloop {
629 | 130 | 44µs |  |  | my($n, $c) = @_;
630 |  |  |  |  |
631 | 130 | 37µs |  |  | $n+=0; # force numeric now, so garbage won't creep into the eval
632 | 130 | 24µs |  |  | croak "negative loopcount $n" if $n<0;
633 | 130 | 24µs |  |  | confess usage unless defined $c;
634 | 130 | 16µs |  |  | my($t0, $t1, $td); # before, after, difference
635 |  |  |  |  |
636 |  |  |  |  | # find package of caller so we can execute code there
637 | 130 | 270µs |  |  | my($curpack) = caller(0);
638 | 130 | 36µs |  |  | my($i, $pack)= 0;
639 | 130 | 320µs |  |  | while (($pack) = caller(++$i)) {
640 | 650 | 1.27ms |  |  | last if $pack ne $curpack;
641 |  |  |  |  | }
642 |  |  |  |  |
643 | 130 | 16µs |  |  | my ($subcode, $subref);
644 | 130 | 89µs |  |  | if (ref $c eq 'CODE') {
645 | 130 | 116µs |  |  | $subcode = "sub { for (1 .. $n) { local \$_; package $pack; &\$c; } }";
646 | 130 | 7.26ms |  |  | $subref = eval $subcode; # spent 992ms executing statements in 2 string evals (merged) # includes 2.44s spent executing 2 calls to 1 sub defined therein. # spent 834ms executing statements in 2 string evals (merged) # includes 2.04s spent executing 2 calls to 1 sub defined therein. # spent 776ms executing statements in 2 string evals (merged) # includes 1.88s spent executing 2 calls to 1 sub defined therein. # spent 201ms executing statements in 4 string evals (merged) # includes 463ms spent executing 4 calls to 1 sub defined therein. # spent 109ms executing statements in 6 string evals (merged) # includes 270ms spent executing 6 calls to 1 sub defined therein. # spent 83.2ms executing statements in 2 string evals (merged) # includes 205ms spent executing 2 calls to 1 sub defined therein. # spent 76.5ms executing statements in 2 string evals (merged) # includes 193ms spent executing 2 calls to 1 sub defined therein. # spent 56.1ms executing statements in 6 string evals (merged) # includes 130ms spent executing 6 calls to 1 sub defined therein. # spent 29.1ms executing statements in 6 string evals (merged) # includes 67.2ms spent executing 6 calls to 1 sub defined therein. # spent 18.2ms executing statements in 8 string evals (merged) # includes 43.0ms spent executing 8 calls to 1 sub defined therein. # spent 11.4ms executing statements in 8 string evals (merged) # includes 24.6ms spent executing 8 calls to 1 sub defined therein. # spent 11.1ms executing statements in 2 string evals (merged) # includes 17.5ms spent executing 2 calls to 1 sub defined therein. # spent 4.57ms executing statements in 8 string evals (merged) # includes 9.99ms spent executing 8 calls to 1 sub defined therein. # spent 2.34ms executing statements in 8 string evals (merged) # includes 6.55ms spent executing 8 calls to 1 sub defined therein. # spent 1.17ms executing statements in 8 string evals (merged) # includes 2.00ms spent executing 8 calls to 1 sub defined therein. # spent 627µs executing statements in 8 string evals (merged) # includes 1.02ms spent executing 8 calls to 1 sub defined therein. # spent 352µs executing statements in 8 string evals (merged) # includes 532µs spent executing 8 calls to 1 sub defined therein. # spent 207µs executing statements in 8 string evals (merged) # includes 283µs spent executing 8 calls to 1 sub defined therein. # spent 139µs executing statements in 8 string evals (merged) # includes 162µs spent executing 8 calls to 1 sub defined therein. # spent 103µs executing statements in 8 string evals (merged) # includes 100µs spent executing 8 calls to 1 sub defined therein. # spent 87µs executing statements in 8 string evals (merged) # includes 71µs spent executing 8 calls to 1 sub defined therein. # spent 77µs executing statements in 8 string evals (merged) # includes 73µs spent executing 8 calls to 1 sub defined therein.
647 |  |  |  |  | }
648 |  |  |  |  | else {
649 |  |  |  |  | $subcode = "sub { for (1 .. $n) { local \$_; package $pack; $c;} }";
650 |  |  |  |  | $subref = _doeval($subcode);
651 |  |  |  |  | }
652 | 130 | 23µs |  |  | croak "runloop unable to compile '$c': $@\ncode: $subcode\n" if $@;
653 | 130 | 18µs |  |  | print STDERR "runloop $n '$subcode'\n" if $Debug;
654 |  |  |  |  |
655 |  |  |  |  | # Wait for the user timer to tick. This makes the error range more like
656 |  |  |  |  | # -0.01, +0. If we don't wait, then it's more like -0.01, +0.01. This
657 |  |  |  |  | # may not seem important, but it significantly reduces the chances of
658 |  |  |  |  | # getting a too low initial $n in the initial, 'find the minimum' loop
659 |  |  |  |  | # in &countit. This, in turn, can reduce the number of calls to
660 |  |  |  |  | # &runloop a lot, and thus reduce additive errors.
661 | 130 | 348µs | 130 | 1.19ms | my $tbase = Benchmark->new(0)->[1]; # spent 1.19ms making 130 calls to Benchmark::new, avg 9µs/call
662 | 130 | 165ms | 106682 | 529ms | while ( ( $t0 = Benchmark->new(0) )->[1] == $tbase ) {} ; # spent 529ms making 106682 calls to Benchmark::new, avg 5µs/call
663 | 130 | 171µs | 130 | 21.8s | $subref->(); # spent 5.57s making 2 calls to Benchmark::__ANON__[(eval 67)[Benchmark.pm:646]:1], avg 2.79s/call # spent 4.96s making 2 calls to Benchmark::__ANON__[(eval 101)[Benchmark.pm:646]:1], avg 2.48s/call # spent 4.93s making 2 calls to Benchmark::__ANON__[(eval 135)[Benchmark.pm:646]:1], avg 2.46s/call # spent 3.46s making 4 calls to Benchmark::__ANON__[(eval 33)[Benchmark.pm:646]:1], avg 864ms/call # spent 666ms making 6 calls to Benchmark::__ANON__[(eval 131)[Benchmark.pm:646]:1], avg 111ms/call # spent 503ms making 2 calls to Benchmark::__ANON__[(eval 100)[Benchmark.pm:646]:1], avg 252ms/call # spent 502ms making 2 calls to Benchmark::__ANON__[(eval 133)[Benchmark.pm:646]:1], avg 251ms/call # spent 335ms making 6 calls to Benchmark::__ANON__[(eval 129)[Benchmark.pm:646]:1], avg 55.8ms/call # spent 288ms making 2 calls to Benchmark::__ANON__[(eval 31)[Benchmark.pm:646]:1], avg 144ms/call # spent 224ms making 8 calls to Benchmark::__ANON__[(eval 125)[Benchmark.pm:646]:1], avg 28.1ms/call # spent 169ms making 6 calls to Benchmark::__ANON__[(eval 127)[Benchmark.pm:646]:1], avg 28.1ms/call # spent 117ms making 8 calls to Benchmark::__ANON__[(eval 123)[Benchmark.pm:646]:1], avg 14.6ms/call # spent 56.8ms making 8 calls to Benchmark::__ANON__[(eval 121)[Benchmark.pm:646]:1], avg 7.10ms/call # spent 28.2ms making 8 calls to Benchmark::__ANON__[(eval 119)[Benchmark.pm:646]:1], avg 3.52ms/call # spent 11.7ms making 8 calls to Benchmark::__ANON__[(eval 117)[Benchmark.pm:646]:1], avg 1.47ms/call # spent 5.86ms making 8 calls to Benchmark::__ANON__[(eval 115)[Benchmark.pm:646]:1], avg 733µs/call # spent 3.00ms making 8 calls to Benchmark::__ANON__[(eval 113)[Benchmark.pm:646]:1], avg 375µs/call # spent 1.53ms making 8 calls to Benchmark::__ANON__[(eval 111)[Benchmark.pm:646]:1], avg 191µs/call # spent 821µs making 8 calls to Benchmark::__ANON__[(eval 109)[Benchmark.pm:646]:1], avg 103µs/call # spent 442µs making 8 calls to Benchmark::__ANON__[(eval 107)[Benchmark.pm:646]:1], avg 55µs/call # spent 260µs making 8 calls to Benchmark::__ANON__[(eval 10)[Benchmark.pm:646]:1], avg 32µs/call # spent 214µs making 8 calls to Benchmark::__ANON__[(eval 103)[Benchmark.pm:646]:1], avg 27µs/call
664 | 130 | 212µs | 130 | 888µs | $t1 = Benchmark->new($n); # spent 888µs making 130 calls to Benchmark::new, avg 7µs/call
665 | 130 | 151µs | 130 | 963µs | $td = &timediff($t1, $t0); # spent 963µs making 130 calls to Benchmark::timediff, avg 7µs/call
666 | 130 | 132µs | 130 | 168µs | timedebug("runloop:",$td); # spent 168µs making 130 calls to Benchmark::timedebug, avg 1µs/call
667 | 130 | 1.05ms |  |  | $td;
668 |  |  |  |  | }
669 |  |  |  |  |
670 | 1 | 300ns |  |  | $_Usage{timeit} = <<'USAGE';
671 |  |  |  |  | usage: $result = timeit($count, 'code' ); or
672 |  |  |  |  | $result = timeit($count, sub { code } );
673 |  |  |  |  | USAGE
674 |  |  |  |  |
675 |  |  |  |  | # spent 22.7s (1.22ms+22.6) within Benchmark::timeit which was called 65 times, avg 348ms/call: # 57 times (1.04ms+2.39s) by Benchmark::countit at line 733, avg 42.0ms/call # 4 times (99µs+18.4s) by Benchmark::countit at line 776, avg 4.59s/call # 4 times (86µs+1.89s) by Benchmark::countit at line 754, avg 473ms/call sub timeit {
676 | 65 | 18µs |  |  | my($n, $code) = @_;
677 | 65 | 9µs |  |  | my($wn, $wc, $wd);
678 |  |  |  |  |
679 | 65 | 58µs |  |  | die usage unless defined $code and
680 |  |  |  |  | (!ref $code or ref $code eq 'CODE');
681 |  |  |  |  |
682 | 65 | 8µs |  |  | printf STDERR "timeit $n $code\n" if $Debug;
683 | 65 | 47µs |  |  | my $cache_key = $n . ( ref( $code ) ? 'c' : 's' );
684 | 65 | 47µs |  |  | if ($Do_Cache && exists $Cache{$cache_key} ) {
685 |  |  |  |  | $wn = $Cache{$cache_key};
686 |  |  |  |  | } else {
687 | 1413767 | 3.00s | 65 | 4.53s | # spent 502ms within Benchmark::__ANON__[/usr/share/perl/5.18/Benchmark.pm:687] which was called 1413702 times, avg 355ns/call: # 447844 times (161ms+0s) by Benchmark::__ANON__[(eval 67)[/usr/share/perl/5.18/Benchmark.pm:646]:1] at line 1 of (eval 67)[Benchmark.pm:646], avg 359ns/call # 362870 times (127ms+0s) by Benchmark::__ANON__[(eval 101)[/usr/share/perl/5.18/Benchmark.pm:646]:1] at line 1 of (eval 101)[Benchmark.pm:646], avg 351ns/call # 338684 times (121ms+0s) by Benchmark::__ANON__[(eval 135)[/usr/share/perl/5.18/Benchmark.pm:646]:1] at line 1 of (eval 135)[Benchmark.pm:646], avg 357ns/call # 86607 times (31.1ms+0s) by Benchmark::__ANON__[(eval 33)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 65)[/usr/share/perl/5.18/Benchmark.pm:646]:1] at line 1 of (eval 33)[Benchmark.pm:646], avg 359ns/call # 49152 times (17.4ms+0s) by Benchmark::__ANON__[(eval 131)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 63)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 97)[/usr/share/perl/5.18/Benchmark.pm:646]:1] at line 1 of (eval 63)[Benchmark.pm:646], avg 353ns/call # 36863 times (13.2ms+0s) by Benchmark::__ANON__[(eval 99)[/usr/share/perl/5.18/Benchmark.pm:646]:1] at line 1 of (eval 99)[Benchmark.pm:646], avg 359ns/call # 34406 times (11.9ms+0s) by Benchmark::__ANON__[(eval 133)[/usr/share/perl/5.18/Benchmark.pm:646]:1] at line 1 of (eval 133)[Benchmark.pm:646], avg 345ns/call # 24576 times (8.58ms+0s) by Benchmark::__ANON__[(eval 129)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 61)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 95)[/usr/share/perl/5.18/Benchmark.pm:646]:1] at line 1 of (eval 61)[Benchmark.pm:646], avg 349ns/call # 12288 times (4.34ms+0s) by Benchmark::__ANON__[(eval 127)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 59)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 93)[/usr/share/perl/5.18/Benchmark.pm:646]:1] at line 1 of (eval 59)[Benchmark.pm:646], avg 353ns/call # 8192 times (2.92ms+0s) by Benchmark::__ANON__[(eval 125)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 29)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 57)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 91)[/usr/share/perl/5.18/Benchmark.pm:646]:1] at line 1 of (eval 29)[Benchmark.pm:646], avg 356ns/call # 4096 times (1.42ms+0s) by Benchmark::__ANON__[(eval 123)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 27)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 55)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 89)[/usr/share/perl/5.18/Benchmark.pm:646]:1] at line 1 of (eval 27)[Benchmark.pm:646], avg 346ns/call # 4032 times (1.39ms+0s) by Benchmark::__ANON__[(eval 31)[/usr/share/perl/5.18/Benchmark.pm:646]:1] at line 1 of (eval 31)[Benchmark.pm:646], avg 344ns/call # 2048 times (690µs+0s) by Benchmark::__ANON__[(eval 121)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 25)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 53)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 87)[/usr/share/perl/5.18/Benchmark.pm:646]:1] at line 1 of (eval 25)[Benchmark.pm:646], avg 337ns/call # 1024 times (362µs+0s) by Benchmark::__ANON__[(eval 119)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 23)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 51)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 85)[/usr/share/perl/5.18/Benchmark.pm:646]:1] at line 1 of (eval 23)[Benchmark.pm:646], avg 353ns/call # 512 times (170µs+0s) by Benchmark::__ANON__[(eval 117)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 21)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 49)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 83)[/usr/share/perl/5.18/Benchmark.pm:646]:1] at line 1 of (eval 21)[Benchmark.pm:646], avg 331ns/call # 256 times (87µs+0s) by Benchmark::__ANON__[(eval 115)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 19)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 47)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 81)[/usr/share/perl/5.18/Benchmark.pm:646]:1] at line 1 of (eval 19)[Benchmark.pm:646], avg 339ns/call # 128 times (47µs+0s) by Benchmark::__ANON__[(eval 113)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 17)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 45)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 79)[/usr/share/perl/5.18/Benchmark.pm:646]:1] at line 1 of (eval 17)[Benchmark.pm:646], avg 370ns/call # 64 times (22µs+0s) by Benchmark::__ANON__[(eval 111)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 15)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 43)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 77)[/usr/share/perl/5.18/Benchmark.pm:646]:1] at line 1 of (eval 15)[Benchmark.pm:646], avg 350ns/call # 32 times (12µs+0s) by Benchmark::__ANON__[(eval 109)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 13)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 41)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 75)[/usr/share/perl/5.18/Benchmark.pm:646]:1] at line 1 of (eval 13)[Benchmark.pm:646], avg 388ns/call # 16 times (7µs+0s) by Benchmark::__ANON__[(eval 107)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 11)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 39)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 73)[/usr/share/perl/5.18/Benchmark.pm:646]:1] at line 1 of (eval 11)[Benchmark.pm:646], avg 425ns/call # 8 times (4µs+0s) by Benchmark::__ANON__[(eval 105)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 37)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 71)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 9)[/usr/share/perl/5.18/Benchmark.pm:646]:1] at line 1 of (eval 9)[Benchmark.pm:646], avg 512ns/call # 4 times (3µs+0s) by Benchmark::__ANON__[(eval 103)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 35)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 69)[/usr/share/perl/5.18/Benchmark.pm:646]:1] or Benchmark::__ANON__[(eval 7)[/usr/share/perl/5.18/Benchmark.pm:646]:1] at line 1 of (eval 7)[Benchmark.pm:646], avg 725ns/call $wn = &runloop($n, ref( $code ) ? sub { } : '' ); # spent 4.53s making 65 calls to Benchmark::runloop, avg 69.7ms/call
688 |  |  |  |  | # Can't let our baseline have any iterations, or they get subtracted
689 |  |  |  |  | # out of the result.
690 | 65 | 29µs |  |  | $wn->[5] = 0;
691 | 65 | 72µs |  |  | $Cache{$cache_key} = $wn;
692 |  |  |  |  | }
693 |  |  |  |  |
694 | 65 | 71µs | 65 | 18.1s | $wc = &runloop($n, $code); # spent 18.1s making 65 calls to Benchmark::runloop, avg 279ms/call
695 |  |  |  |  |
696 | 65 | 69µs | 65 | 321µs | $wd = timediff($wc, $wn); # spent 321µs making 65 calls to Benchmark::timediff, avg 5µs/call
697 | 65 | 52µs | 65 | 58µs | timedebug("timeit: ",$wc); # spent 58µs making 65 calls to Benchmark::timedebug, avg 894ns/call
698 | 65 | 44µs | 65 | 47µs | timedebug(" - ",$wn); # spent 47µs making 65 calls to Benchmark::timedebug, avg 729ns/call
699 | 65 | 41µs | 65 | 43µs | timedebug(" = ",$wd); # spent 43µs making 65 calls to Benchmark::timedebug, avg 658ns/call
700 |  |  |  |  |
701 | 65 | 134µs |  |  | $wd;
702 |  |  |  |  | }
703 |  |  |  |  |
704 |  |  |  |  |
705 | 1 | 100ns |  |  | my $default_for = 3;
706 | 1 | 100ns |  |  | my $min_for = 0.1;
707 |  |  |  |  |
708 |  |  |  |  |
709 | 1 | 300ns |  |  | $_Usage{countit} = <<'USAGE';
710 |  |  |  |  | usage: $result = countit($time, 'code' ); or
711 |  |  |  |  | $result = countit($time, sub { code } );
712 |  |  |  |  | USAGE
713 |  |  |  |  |
714 |  |  |  |  | # spent 22.7s (347µs+22.7) within Benchmark::countit which was called 4 times, avg 5.66s/call: # 4 times (347µs+22.7s) by Benchmark::timethis at line 825, avg 5.66s/call sub countit {
715 | 4 | 2µs |  |  | my ( $tmax, $code ) = @_;
716 |  |  |  |  |
717 | 4 | 2µs |  |  | die usage unless @_;
718 |  |  |  |  |
719 | 4 | 3µs |  |  | if ( not defined $tmax or $tmax == 0 ) {
720 |  |  |  |  | $tmax = $default_for;
721 |  |  |  |  | } elsif ( $tmax < 0 ) {
722 |  |  |  |  | $tmax = -$tmax;
723 |  |  |  |  | }
724 |  |  |  |  |
725 | 4 | 2µs |  |  | die "countit($tmax, ...): timelimit cannot be less than $min_for.\n"
726 |  |  |  |  | if $tmax < $min_for;
727 |  |  |  |  |
728 | 4 | 500ns |  |  | my ($n, $tc);
729 |  |  |  |  |
730 |  |  |  |  | # First find the minimum $n that gives a significant timing.
731 | 4 | 1µs |  |  | my $zeros=0;
732 | 4 | 30µs |  |  | for ($n = 1; ; $n *= 2 ) {
733 | 57 | 55µs | 57 | 2.39s | my $td = timeit($n, $code); # spent 2.39s making 57 calls to Benchmark::timeit, avg 42.0ms/call
734 | 57 | 35µs |  |  | $tc = $td->[1] + $td->[2];
735 | 57 | 34µs |  |  | if ( $tc <= 0 and $n > 1024 ) {
736 |  |  |  |  | ++$zeros > 16
737 |  |  |  |  | and die "Timing is consistently zero in estimation loop, cannot benchmark. N=$n\n";
738 |  |  |  |  | } else {
739 | 57 | 16µs |  |  | $zeros = 0;
740 |  |  |  |  | }
741 | 57 | 41µs |  |  | last if $tc > 0.1;
742 |  |  |  |  | }
743 |  |  |  |  |
744 | 4 | 1µs |  |  | my $nmin = $n;
745 |  |  |  |  |
746 |  |  |  |  | # Get $n high enough that we can guess the final $n with some accuracy.
747 | 4 | 2µs |  |  | my $tpra = 0.1 * $tmax; # Target/time practice.
748 | 4 | 2µs |  |  | while ( $tc < $tpra ) {
749 |  |  |  |  | # The 5% fudge is to keep us from iterating again all
750 |  |  |  |  | # that often (this speeds overall responsiveness when $tmax is big
751 |  |  |  |  | # and we guess a little low). This does not noticably affect
752 |  |  |  |  | # accuracy since we're not counting these times.
753 | 4 | 8µs |  |  | $n = int( $tpra * 1.05 * $n / $tc ); # Linear approximation.
754 | 4 | 6µs | 4 | 1.89s | my $td = timeit($n, $code); # spent 1.89s making 4 calls to Benchmark::timeit, avg 473ms/call
755 | 4 | 5µs |  |  | my $new_tc = $td->[1] + $td->[2];
756 |  |  |  |  | # Make sure we are making progress.
757 | 4 | 7µs |  |  | $tc = $new_tc > 1.2 * $tc ? $new_tc : 1.2 * $tc;
758 |  |  |  |  | }
759 |  |  |  |  |
760 |  |  |  |  | # Now, do the 'for real' timing(s), repeating until we exceed
761 |  |  |  |  | # the max.
762 | 4 | 1µs |  |  | my $ntot = 0;
763 | 4 | 800ns |  |  | my $rtot = 0;
764 | 4 | 1µs |  |  | my $utot = 0.0;
765 | 4 | 1µs |  |  | my $stot = 0.0;
766 | 4 | 1µs |  |  | my $cutot = 0.0;
767 | 4 | 900ns |  |  | my $cstot = 0.0;
768 | 4 | 500ns |  |  | my $ttot = 0.0;
769 |  |  |  |  |
770 |  |  |  |  | # The 5% fudge is because $n is often a few % low even for routines
771 |  |  |  |  | # with stable times and avoiding extra timeit()s is nice for
772 |  |  |  |  | # accuracy's sake.
773 | 4 | 5µs |  |  | $n = int( $n * ( 1.05 * $tmax / $tc ) );
774 | 4 | 800ns |  |  | $zeros=0;
775 | 4 | 500ns |  |  | while () {
776 | 4 | 6µs | 4 | 18.4s | my $td = timeit($n, $code); # spent 18.4s making 4 calls to Benchmark::timeit, avg 4.59s/call
777 | 4 | 3µs |  |  | $ntot += $n;
778 | 4 | 2µs |  |  | $rtot += $td->[0];
779 | 4 | 2µs |  |  | $utot += $td->[1];
780 | 4 | 2µs |  |  | $stot += $td->[2];
781 | 4 | 1µs |  |  | $cutot += $td->[3];
782 | 4 | 2µs |  |  | $cstot += $td->[4];
783 | 4 | 800ns |  |  | $ttot = $utot + $stot;
784 | 4 | 6µs |  |  | last if $ttot >= $tmax;
785 |  |  |  |  | if ( $ttot <= 0 ) {
786 |  |  |  |  | ++$zeros > 16
787 |  |  |  |  | and die "Timing is consistently zero, cannot benchmark. N=$n\n";
788 |  |  |  |  | } else {
789 |  |  |  |  | $zeros = 0;
790 |  |  |  |  | }
791 |  |  |  |  | $ttot = 0.01 if $ttot < 0.01;
792 |  |  |  |  | my $r = $tmax / $ttot - 1; # Linear approximation.
793 |  |  |  |  | $n = int( $r * $ntot );
794 |  |  |  |  | $n = $nmin if $n < $nmin;
795 |  |  |  |  | }
796 |  |  |  |  |
797 | 4 | 16µs |  |  | return bless [ $rtot, $utot, $stot, $cutot, $cstot, $ntot ];
798 |  |  |  |  | }
799 |  |  |  |  |
800 |  |  |  |  | # --- Functions implementing high-level time-then-print utilities
801 |  |  |  |  |
802 |  |  |  |  | # spent 12µs within Benchmark::n_to_for which was called 5 times, avg 2µs/call: # 4 times (9µs+0s) by Benchmark::timethis at line 824, avg 2µs/call # once (3µs+0s) by Benchmark::timethese at line 867 sub n_to_for {
803 | 5 | 2µs |  |  | my $n = shift;
804 | 5 | 17µs |  |  | return $n == 0 ? $default_for : $n < 0 ? -$n : undef;
805 |  |  |  |  | }
806 |  |  |  |  |
807 | 1 | 300ns |  |  | $_Usage{timethis} = <<'USAGE';
808 |  |  |  |  | usage: $result = timethis($time, 'code' ); or
809 |  |  |  |  | $result = timethis($time, sub { code } );
810 |  |  |  |  | USAGE
811 |  |  |  |  |
812 |  |  |  |  | # spent 22.7s (97µs+22.7) within Benchmark::timethis which was called 4 times, avg 5.66s/call: # 4 times (97µs+22.7s) by Benchmark::timethese at line 877, avg 5.66s/call sub timethis{
813 | 4 | 2µs |  |  | my($n, $code, $title, $style) = @_;
814 | 4 | 600ns |  |  | my($t, $forn);
815 |  |  |  |  |
816 | 4 | 5µs |  |  | die usage unless defined $code and
817 |  |  |  |  | (!ref $code or ref $code eq 'CODE');
818 |  |  |  |  |
819 | 4 | 3µs |  |  | if ( $n > 0 ) {
820 |  |  |  |  | croak "non-integer loopcount $n, stopped" if int($n)<$n;
821 |  |  |  |  | $t = timeit($n, $code);
822 |  |  |  |  | $title = "timethis $n" unless defined $title;
823 |  |  |  |  | } else {
824 | 4 | 5µs | 4 | 9µs | my $fort = n_to_for( $n ); # spent 9µs making 4 calls to Benchmark::n_to_for, avg 2µs/call
825 | 4 | 6µs | 4 | 22.7s | $t = countit( $fort, $code ); # spent 22.7s making 4 calls to Benchmark::countit, avg 5.66s/call
826 | 4 | 2µs |  |  | $title = "timethis for $fort" unless defined $title;
827 | 4 | 4µs |  |  | $forn = $t->[-1];
828 |  |  |  |  | }
829 | 4 | 16µs |  |  | local $| = 1;
830 | 4 | 1µs |  |  | $style = "" unless defined $style;
831 | 4 | 3µs |  |  | printf("%10s: ", $title) unless $style eq 'none';
832 | 4 | 1µs |  |  | print timestr($t, $style, $Default_Format),"\n" unless $style eq 'none';
833 |  |  |  |  |
834 | 4 | 2µs |  |  | $n = $forn if defined $forn;
835 |  |  |  |  |
836 |  |  |  |  | # A conservative warning to spot very silly tests.
837 |  |  |  |  | # Don't assume that your benchmark is ok simply because
838 |  |  |  |  | # you don't get this warning!
839 | 4 | 20µs | 8 | 20µs | print " (warning: too few iterations for a reliable count)\n" # spent 10µs making 4 calls to Benchmark::cpu_a, avg 3µs/call # spent 9µs making 4 calls to Benchmark::real, avg 2µs/call
840 |  |  |  |  | if $n < $Min_Count
841 |  |  |  |  | || ($t->real < 1 && $n < 1000)
842 |  |  |  |  | || $t->cpu_a < $Min_CPU;
843 | 4 | 12µs |  |  | $t;
844 |  |  |  |  | }
845 |  |  |  |  |
846 |  |  |  |  |
847 | 1 | 300ns |  |  | $_Usage{timethese} = <<'USAGE';
848 |  |  |  |  | usage: timethese($count, { Name1 => 'code1', ... }); or
849 |  |  |  |  | timethese($count, { Name1 => sub { code1 }, ... });
850 |  |  |  |  | USAGE
851 |  |  |  |  |
852 |  |  |  |  | # spent 22.7s (37µs+22.7) within Benchmark::timethese which was called: # once (37µs+22.7s) by Benchmark::cmpthese at line 903 sub timethese{
853 | 1 | 600ns |  |  | my($n, $alt, $style) = @_;
854 | 1 | 500ns |  |  | die usage unless ref $alt eq 'HASH';
855 |  |  |  |  |
856 | 1 | 14µs | 1 | 6µs | my @names = sort keys %$alt; # spent 6µs making 1 call to Benchmark::CORE:sort
857 | 1 | 200ns |  |  | $style = "" unless defined $style;
858 | 1 | 300ns |  |  | print "Benchmark: " unless $style eq 'none';
859 | 1 | 600ns |  |  | if ( $n > 0 ) {
860 |  |  |  |  | croak "non-integer loopcount $n, stopped" if int($n)<$n;
861 |  |  |  |  | print "timing $n iterations of" unless $style eq 'none';
862 |  |  |  |  | } else {
863 | 1 | 300ns |  |  | print "running" unless $style eq 'none';
864 |  |  |  |  | }
865 | 1 | 200ns |  |  | print " ", join(', ',@names) unless $style eq 'none';
866 | 1 | 300ns |  |  | unless ( $n > 0 ) {
867 | 1 | 1µs | 1 | 3µs | my $for = n_to_for( $n ); # spent 3µs making 1 call to Benchmark::n_to_for
868 | 1 | 300ns |  |  | print ", each" if $n > 1 && $style ne 'none';
869 | 1 | 400ns |  |  | print " for at least $for CPU seconds" unless $style eq 'none';
870 |  |  |  |  | }
871 | 1 | 100ns |  |  | print "...\n" unless $style eq 'none';
872 |  |  |  |  |
873 |  |  |  |  | # we could save the results in an array and produce a summary here
874 |  |  |  |  | # sum, min, max, avg etc etc
875 | 1 | 100ns |  |  | my %results;
876 | 1 | 800ns |  |  | foreach my $name (@names) {
877 | 4 | 14µs | 4 | 22.7s | $results{$name} = timethis ($n, $alt -> {$name}, $name, $style); # spent 22.7s making 4 calls to Benchmark::timethis, avg 5.66s/call
878 |  |  |  |  | }
879 |  |  |  |  |
880 | 1 | 5µs |  |  | return \%results;
881 |  |  |  |  | }
882 |  |  |  |  |
883 |  |  |  |  |
884 | 1 | 300ns |  |  | $_Usage{cmpthese} = <<'USAGE';
885 |  |  |  |  | usage: cmpthese($count, { Name1 => 'code1', ... }); or
886 |  |  |  |  | cmpthese($count, { Name1 => sub { code1 }, ... }); or
887 |  |  |  |  | cmpthese($result, $style);
888 |  |  |  |  | USAGE
889 |  |  |  |  |
890 |  |  |  |  | # spent 22.7s (177µs+22.7) within Benchmark::cmpthese which was called: # once (177µs+22.7s) by main::RUNTIME at line 13 of examples/benchmark4.pl sub cmpthese{
891 | 1 | 300ns |  |  | my ($results, $style);
892 |  |  |  |  |
893 |  |  |  |  | # $count can be a blessed object.
894 | 1 | 6µs |  |  | if ( ref $_[0] eq 'HASH' ) {
895 |  |  |  |  | ($results, $style) = @_;
896 |  |  |  |  | }
897 |  |  |  |  | else {
898 | 1 | 1µs |  |  | my($count, $code) = @_[0,1];
899 | 1 | 400ns |  |  | $style = $_[2] if defined $_[2];
900 |  |  |  |  |
901 | 1 | 800ns |  |  | die usage unless ref $code eq 'HASH';
902 |  |  |  |  |
903 | 1 | 2µs | 1 | 22.7s | $results = timethese($count, $code, ($style || "none")); # spent 22.7s making 1 call to Benchmark::timethese
904 |  |  |  |  | }
905 |  |  |  |  |
906 | 1 | 1µs |  |  | $style = "" unless defined $style;
907 |  |  |  |  |
908 |  |  |  |  | # Flatten in to an array of arrays with the name as the first field
909 | 1 | 10µs |  |  | my @vals = map{ [ $_, @{$results->{$_}} ] } keys %$results;
910 |  |  |  |  |
911 | 1 | 1µs |  |  | for (@vals) {
912 |  |  |  |  | # The epsilon fudge here is to prevent div by 0. Since clock
913 |  |  |  |  | # resolutions are much larger, it's below the noise floor.
914 | 4 | 1µs |  |  | my $elapsed = do {
915 | 4 | 2µs |  |  | if ($style eq 'nop') {$_->[4]+$_->[5]}
916 | 4 | 4µs |  |  | elsif ($style eq 'noc') {$_->[2]+$_->[3]}
917 |  |  |  |  | else {$_->[2]+$_->[3]+$_->[4]+$_->[5]}
918 |  |  |  |  | };
919 | 4 | 2µs |  |  | my $rate = $_->[6]/(($elapsed)+0.000000000000001);
920 | 4 | 2µs |  |  | $_->[7] = $rate;
921 |  |  |  |  | }
922 |  |  |  |  |
923 |  |  |  |  | # Sort by rate
924 | 1 | 15µs | 1 | 11µs | @vals = sort { $a->[7] <=> $b->[7] } @vals; # spent 11µs making 1 call to Benchmark::CORE:sort
925 |  |  |  |  |
926 |  |  |  |  | # If more than half of the rates are greater than one...
927 | 1 | 2µs |  |  | my $display_as_rate = @vals ? ($vals[$#vals>>1]->[7] > 1) : 0;
928 |  |  |  |  |
929 | 1 | 200ns |  |  | my @rows;
930 | 1 | 200ns |  |  | my @col_widths;
931 |  |  |  |  |
932 |  |  |  |  | my @top_row = (
933 |  |  |  |  | '',
934 |  |  |  |  | $display_as_rate ? 'Rate' : 's/iter',
935 | 1 | 3µs |  |  | map { $_->[0] } @vals
936 |  |  |  |  | );
937 |  |  |  |  |
938 | 1 | 600ns |  |  | push @rows, \@top_row;
939 | 1 | 2µs |  |  | @col_widths = map { length( $_ ) } @top_row;
940 |  |  |  |  |
941 |  |  |  |  | # Build the data rows
942 |  |  |  |  | # We leave the last column in even though it never has any data. Perhaps
943 |  |  |  |  | # it should go away. Also, perhaps a style for a single column of
944 |  |  |  |  | # percentages might be nice.
945 | 1 | 900ns |  |  | for my $row_val ( @vals ) {
946 | 4 | 200ns |  |  | my @row;
947 |  |  |  |  |
948 |  |  |  |  | # Column 0 = test name
949 | 4 | 2µs |  |  | push @row, $row_val->[0];
950 | 4 | 2µs |  |  | $col_widths[0] = length( $row_val->[0] )
951 |  |  |  |  | if length( $row_val->[0] ) > $col_widths[0];
952 |  |  |  |  |
953 |  |  |  |  | # Column 1 = performance
954 | 4 | 600ns |  |  | my $row_rate = $row_val->[7];
955 |  |  |  |  |
956 |  |  |  |  | # We assume that we'll never get a 0 rate.
957 | 4 | 700ns |  |  | my $rate = $display_as_rate ? $row_rate : 1 / $row_rate;
958 |  |  |  |  |
959 |  |  |  |  | # Only give a few decimal places before switching to sci. notation,
960 |  |  |  |  | # since the results aren't usually that accurate anyway.
961 | 4 | 1µs |  |  | my $format =
962 |  |  |  |  | $rate >= 100 ?
963 |  |  |  |  | "%0.0f" :
964 |  |  |  |  | $rate >= 10 ?
965 |  |  |  |  | "%0.1f" :
966 |  |  |  |  | $rate >= 1 ?
967 |  |  |  |  | "%0.2f" :
968 |  |  |  |  | $rate >= 0.1 ?
969 |  |  |  |  | "%0.3f" :
970 |  |  |  |  | "%0.2e";
971 |  |  |  |  |
972 | 4 | 1µs |  |  | $format .= "/s"
973 |  |  |  |  | if $display_as_rate;
974 |  |  |  |  |
975 | 4 | 18µs |  |  | my $formatted_rate = sprintf( $format, $rate );
976 | 4 | 2µs |  |  | push @row, $formatted_rate;
977 | 4 | 1µs |  |  | $col_widths[1] = length( $formatted_rate )
978 |  |  |  |  | if length( $formatted_rate ) > $col_widths[1];
979 |  |  |  |  |
980 |  |  |  |  | # Columns 2..N = performance ratios
981 | 4 | 800ns |  |  | my $skip_rest = 0;
982 | 4 | 7µs |  |  | for ( my $col_num = 0 ; $col_num < @vals ; ++$col_num ) {
983 | 16 | 3µs |  |  | my $col_val = $vals[$col_num];
984 | 16 | 1µs |  |  | my $out;
985 | 16 | 6µs |  |  | if ( $skip_rest ) {
986 |  |  |  |  | $out = '';
987 |  |  |  |  | }
988 |  |  |  |  | elsif ( $col_val->[0] eq $row_val->[0] ) {
989 |  |  |  |  | $out = "--";
990 |  |  |  |  | # $skip_rest = 1;
991 |  |  |  |  | }
992 |  |  |  |  | else {
993 | 12 | 2µs |  |  | my $col_rate = $col_val->[7];
994 | 12 | 11µs |  |  | $out = sprintf( "%.0f%%", 100*$row_rate/$col_rate - 100 );
995 |  |  |  |  | }
996 | 16 | 6µs |  |  | push @row, $out;
997 | 16 | 4µs |  |  | $col_widths[$col_num+2] = length( $out )
998 |  |  |  |  | if length( $out ) > $col_widths[$col_num+2];
999 |  |  |  |  |
1000 |  |  |  |  | # A little wierdness to set the first column width properly
1001 | 16 | 6µs |  |  | $col_widths[$col_num+2] = length( $col_val->[0] )
1002 |  |  |  |  | if length( $col_val->[0] ) > $col_widths[$col_num+2];
1003 |  |  |  |  | }
1004 | 4 | 3µs |  |  | push @rows, \@row;
1005 |  |  |  |  | }
1006 |  |  |  |  |
1007 | 1 | 500ns |  |  | return \@rows if $style eq "none";
1008 |  |  |  |  |
1009 |  |  |  |  | # Equalize column widths in the chart as much as possible without
1010 |  |  |  |  | # exceeding 80 characters. This does not use or affect cols 0 or 1.
1011 |  |  |  |  | my @sorted_width_refs =
1012 | 5 | 10µs | 1 | 3µs | sort { $$a <=> $$b } map { \$_ } @col_widths[2..$#col_widths]; # spent 3µs making 1 call to Benchmark::CORE:sort
1013 | 1 | 600ns |  |  | my $max_width = ${$sorted_width_refs[-1]};
1014 |  |  |  |  |
1015 | 1 | 500ns |  |  | my $total = @col_widths - 1 ;
1016 | 7 | 2µs |  |  | for ( @col_widths ) { $total += $_ }
1017 |  |  |  |  |
1018 |  |  |  |  | STRETCHER:
1019 | 1 | 700ns |  |  | while ( $total < 80 ) {
1020 |  |  |  |  | my $min_width = ${$sorted_width_refs[0]};
1021 |  |  |  |  | last
1022 |  |  |  |  | if $min_width == $max_width;
1023 |  |  |  |  | for ( @sorted_width_refs ) {
1024 |  |  |  |  | last
1025 |  |  |  |  | if $$_ > $min_width;
1026 |  |  |  |  | ++$$_;
1027 |  |  |  |  | ++$total;
1028 |  |  |  |  | last STRETCHER
1029 |  |  |  |  | if $total >= 80;
1030 |  |  |  |  | }
1031 |  |  |  |  | }
1032 |  |  |  |  |
1033 |  |  |  |  | # Dump the output
1034 | 1 | 6µs |  |  | my $format = join( ' ', map { "%${_}s" } @col_widths ) . "\n";
1035 | 1 | 1µs |  |  | substr( $format, 1, 0 ) = '-';
1036 | 1 | 900ns |  |  | for ( @rows ) {
1037 | 5 | 90µs | 5 | 68µs | printf $format, @$_; # spent 68µs making 5 calls to Benchmark::CORE:prtf, avg 14µs/call
1038 |  |  |  |  | }
1039 |  |  |  |  |
1040 | 1 | 9µs |  |  | return \@rows ;
1041 |  |  |  |  | }
1042 |  |  |  |  |
1043 |  |  |  |  |
1044 | 1 | 11µs |  |  | 1;
|  |  |  |  | # spent 68µs within Benchmark::CORE:prtf which was called 5 times, avg 14µs/call: # 5 times (68µs+0s) by Benchmark::cmpthese at line 1037, avg 14µs/call sub Benchmark::CORE:prtf; # opcode
|  |  |  |  | # spent 20µs within Benchmark::CORE:sort which was called 3 times, avg 7µs/call: # once (11µs+0s) by Benchmark::cmpthese at line 924 # once (6µs+0s) by Benchmark::timethese at line 856 # once (3µs+0s) by Benchmark::cmpthese at line 1012 sub Benchmark::CORE:sort; # opcode