$t = countit( $fort, $code );
$title = "timethis for $fort" unless defined $title;
$forn = $t->[-1];
}
local $| = 1;
$style = "" unless defined $style;
printf("%10s: ", $title) unless $style eq 'none';
print timestr($t, $style, $Default_Format),"\n" unless $style eq 'none';
$n = $forn if defined $forn;
# A conservative warning to spot very silly tests.
# Don't assume that your benchmark is ok simply because
# you don't get this warning!
print " (warning: too few iterations for a reliable count)\n"
if $n < $Min_Count
|| ($t->real < 1 && $n < 1000)
|| $t->cpu_a < $Min_CPU;
$t;
}
$_Usage{timethese} = <<'USAGE';
usage: timethese($count, { Name1 => 'code1', ... }); or
timethese($count, { Name1 => sub { code1 }, ... });
USAGE
sub timethese{
my($n, $alt, $style) = @_;
die usage unless ref $alt eq 'HASH';
my @names = sort keys %$alt;
$style = "" unless defined $style;
print "Benchmark: " unless $style eq 'none';
if ( $n > 0 ) {
croak "non-integer loopcount $n, stopped" if int($n)<$n;
print "timing $n iterations of" unless $style eq 'none';
} else {
print "running" unless $style eq 'none';
}
print " ", join(', ',@names) unless $style eq 'none';
unless ( $n > 0 ) {
my $for = n_to_for( $n );
print ", each" if $n > 1 && $style ne 'none';
print " for at least $for CPU seconds" unless $style eq 'none';
}
print "...\n" unless $style eq 'none';
# we could save the results in an array and produce a summary here
# sum, min, max, avg etc etc
my %results;
foreach my $name (@names) {
$results{$name} = timethis ($n, $alt -> {$name}, $name, $style);
}
return \%results;
}
$_Usage{cmpthese} = <<'USAGE';
usage: cmpthese($count, { Name1 => 'code1', ... }); or
cmpthese($count, { Name1 => sub { code1 }, ... }); or
cmpthese($result, $style);
USAGE
sub cmpthese{
my ($results, $style);
if( ref $_[0] ) {
($results, $style) = @_;
}
else {
my($count, $code) = @_[0,1];
$style = $_[2] if defined $_[2];
die usage unless ref $code eq 'HASH';
$results = timethese($count, $code, ($style || "none"));
}
$style = "" unless defined $style;
# Flatten in to an array of arrays with the name as the first field
my @vals = map{ [ $_, @{$results->{$_}} ] } keys %$results;
for (@vals) {
# The epsilon fudge here is to prevent div by 0. Since clock
# resolutions are much larger, it's below the noise floor.
my $rate = $_->[6] / (( $style eq 'nop' ? $_->[4] + $_->[5]
: $_->[2] + $_->[3]) + 0.000000000000001 );
$_->[7] = $rate;
}
# Sort by rate
@vals = sort { $a->[7] <=> $b->[7] } @vals;
# If more than half of the rates are greater than one...
my $display_as_rate = @vals ? ($vals[$#vals>>1]->[7] > 1) : 0;
my @rows;
=9= |