clearcache clearallcache disablecache enablecache);
%EXPORT_TAGS=( all => [ @EXPORT, @EXPORT_OK ] ) ;
-$VERSION = 1.17;
+$VERSION = 1.19;
# --- ':hireswallclock' special handling
# getting a too low initial $n in the initial, 'find the minimum' loop
# in &countit. This, in turn, can reduce the number of calls to
# &runloop a lot, and thus reduce additive errors.
+ #
+ # Note that its possible for the act of reading the system clock to
+ # burn lots of system CPU while we burn very little user clock in the
+ # busy loop, which can cause the loop to run for a very long wall time.
+ # So gradually ramp up the duration of the loop. See RT #122003
+ #
my $tbase = Benchmark->new(0)->[1];
- while ( ( $t0 = Benchmark->new(0) )->[1] == $tbase ) {} ;
+ my $limit = 1;
+ while ( ( $t0 = Benchmark->new(0) )->[1] == $tbase ) {
+ for (my $i=0; $i < $limit; $i++) { my $x = $i / 1.5 } # burn user CPU
+ $limit *= 1.1;
+ }
$subref->();
$t1 = Benchmark->new($n);
$td = &timediff($t1, $t0);
# First find the minimum $n that gives a significant timing.
my $zeros=0;
for ($n = 1; ; $n *= 2 ) {
+ my $t0 = Benchmark->new(0);
my $td = timeit($n, $code);
+ my $t1 = Benchmark->new(0);
$tc = $td->[1] + $td->[2];
if ( $tc <= 0 and $n > 1024 ) {
- ++$zeros > 16
- and die "Timing is consistently zero in estimation loop, cannot benchmark. N=$n\n";
+ my $d = timediff($t1, $t0);
+ # note that $d is the total CPU time taken to call timeit(),
+ # while $tc is is difference in CPU secs between the empty run
+ # and the code run. If the code is trivial, its possible
+ # for $d to get large while $tc is still zero (or slightly
+ # negative). Bail out once timeit() starts taking more than a
+ # few seconds without noticeable difference.
+ if ($d->[1] + $d->[2] > 8
+ || ++$zeros > 16)
+ {
+ die "Timing is consistently zero in estimation loop, cannot benchmark. N=$n\n";
+ }
} else {
$zeros = 0;
}