410 lines
8.8 KiB
Perl
Executable File
410 lines
8.8 KiB
Perl
Executable File
#!/usr/bin/perl5 -- # -*-Perl-*-
|
|
|
|
$Usage = "Usage: $0 [-l][-i ignore_test][-N ntrials] logfile ...";
|
|
|
|
$TIMEOUT_TM = 50.0; # times > this are timeouts
|
|
$avgonly = 1; # print averages only, or long list
|
|
$ntrials = 20; # number of trials to use from logfile
|
|
|
|
$tnamelen = 24; # test name field length
|
|
|
|
# process options
|
|
while ($ARGV[0] =~ /^-.*/) {
|
|
|
|
if ($ARGV[0] eq "-i") {
|
|
$ignore = $ARGV[1];
|
|
$ignore_tests[$#ignore_tests + 1] = $ignore;
|
|
shift; shift;
|
|
next;
|
|
}
|
|
|
|
if ($ARGV[0] eq "-l") {
|
|
$avgonly = 0;
|
|
shift;
|
|
next;
|
|
}
|
|
|
|
if ($ARGV[0] =~ /^-N/) {
|
|
$ntrials = $ARGV[1];
|
|
die "invalid number $ntrials\n$Usage\n" if $ntrials <= 0;
|
|
shift; shift;
|
|
next;
|
|
}
|
|
|
|
die "invalid flag: $ARGV[0]\n$Usage\n";
|
|
}
|
|
|
|
die $Usage if $#ARGV < 0;
|
|
|
|
|
|
# read in each of the logfiles
|
|
foreach $f ( @ARGV ) {
|
|
|
|
# %timesref is an associative array indexed by the
|
|
# logfile name. The values are references to another
|
|
# associative array indexed by test names. The values
|
|
# of this array are strings which contain a space-separated
|
|
# list of test times for this test from this logfile.
|
|
|
|
$timesref{$f} = &read_logfile($f);
|
|
|
|
$logfiles[$#logfiles + 1] = $f;
|
|
}
|
|
|
|
|
|
$avgonly ? &printavg : &printlong;
|
|
|
|
exit;
|
|
|
|
|
|
# Print out the average summary
|
|
sub printavg {
|
|
# inter column space
|
|
$ics = " ";
|
|
|
|
|
|
# print column keys
|
|
foreach $i ( 0..$#logfiles ) {
|
|
$id = $logfiles[$i];
|
|
$id =~ s+^.*/++; # just print basename
|
|
$id =~ s/^log\.//;
|
|
printf ' ' x $tnamelen . $ics . "%d = %s\n", $i, $id;
|
|
}
|
|
print "\n";
|
|
|
|
|
|
# print column headers
|
|
print ' ' x $tnamelen, $ics, " 0 ";
|
|
foreach $i ( 1..$#logfiles ) {
|
|
printf $ics . " %2d ", $i;
|
|
}
|
|
print "\n";
|
|
|
|
# print column -------
|
|
print ' ' x $tnamelen, $ics, "-----";
|
|
foreach $i ( 1..$#logfiles ) {
|
|
print $ics, '-' x 14;
|
|
}
|
|
print "\n";
|
|
|
|
|
|
$baselog = shift @logfiles;
|
|
$basetm = $timesref{$baselog};
|
|
|
|
# The keys of %alltests are all the unique test names
|
|
# from all the log files. Note that a test name may
|
|
# not appear in every logfile.
|
|
|
|
foreach $t (sort keys %alltests) {
|
|
printf "%-$tnamelen.$tnamelen" . "s", $t;
|
|
|
|
@times = split(' ', $$basetm{$t});
|
|
$baseav = &average(@times);
|
|
|
|
printf $ics . "%5.2f", $baseav if $baseav;
|
|
printf $ics . " N/A " if !$baseav;
|
|
|
|
$both_avs = 0;
|
|
foreach $log (@logfiles) {
|
|
@times = split(' ', ${ $timesref{$log} }{$t});
|
|
$av = &average(@times);
|
|
|
|
# If we have both averages, compute percent change
|
|
if ($baseav && $av) {
|
|
|
|
$pchg = 100.0 * ($av - $baseav) / $baseav;
|
|
printf $ics . "%5.2f (%5.1f%%)", $av, $pchg;
|
|
|
|
$both_avs++;
|
|
|
|
# No base value? Print value without percent change.
|
|
} elsif ($av) {
|
|
printf $ics . "%5.2f ( N/A )", $av;
|
|
|
|
# No value for this test from this logfile.
|
|
} else {
|
|
printf $ics . " N/A ( N/A )";
|
|
}
|
|
}
|
|
print "\n";
|
|
|
|
|
|
# If we had both averages for all of the logfiles
|
|
# add the averages to each of the running totals.
|
|
if ($both_avs == $#logfiles + 1) {
|
|
$basetot += $baseav;
|
|
|
|
foreach $log (@logfiles) {
|
|
@times = split(' ', ${ $timesref{$log} }{$t});
|
|
$av = &average(@times);
|
|
$avtot{$log} += $av;
|
|
}
|
|
}
|
|
}
|
|
|
|
print "\n";
|
|
printf "%-" . $tnamelen . "s", "TOTAL";
|
|
printf ' ' x (length($ics)-1) . "%6.2f", $basetot;
|
|
|
|
for $log (@logfiles) {
|
|
$pchg = 100.0 * ($avtot{$log} - $basetot) / $basetot;
|
|
|
|
printf ' ' x (length($ics)-1) . "%6.2f (%5.1f%%)",
|
|
$avtot{$log}, $pchg;
|
|
}
|
|
print "\n";
|
|
}
|
|
|
|
|
|
sub printlong {
|
|
# inter column space
|
|
$ics = " ";
|
|
|
|
|
|
# print column keys
|
|
foreach $i ( 0..$#logfiles ) {
|
|
$id = $logfiles[$i];
|
|
$id =~ s/^log\.//;
|
|
printf ' ' x 14 . $ics . "%d = %s\n", $i, $id;
|
|
}
|
|
print "\n";
|
|
|
|
|
|
# print column headers
|
|
print ' ' x 14, $ics, " 0 ";
|
|
foreach $i ( 1..$#logfiles ) {
|
|
printf $ics . " %2d ", $i;
|
|
}
|
|
print "\n";
|
|
|
|
# print column -------
|
|
print ' ' x 14, $ics, "-----";
|
|
foreach $i ( 1..$#logfiles ) {
|
|
print $ics, '-' x 14;
|
|
}
|
|
print "\n";
|
|
|
|
|
|
$baselog = shift @logfiles;
|
|
$basetm = $timesref{$baselog};
|
|
|
|
# The keys of %alltests are all the unique test names
|
|
# from all the log files. Note that a test name may
|
|
# not appear every logfile.
|
|
|
|
foreach $t (sort keys %alltests) {
|
|
# print test name
|
|
printf "%s\n", $t;
|
|
|
|
@times = split(' ', $$basetm{$t});
|
|
($basehi, $baselo, $basetot) = ×_hilotot(@times);
|
|
|
|
$basen = $#times + 1;
|
|
$baseav = $basen ? $basetot / $basen : 0;
|
|
|
|
$basestdev = &standard_deviation($baseav, @times);
|
|
|
|
|
|
# ================
|
|
# Print Entries
|
|
printf " %-10s", "Entries:";
|
|
printf $ics . "%2d ", $basen;
|
|
|
|
foreach $log (@logfiles) {
|
|
@times = split(' ', ${ $timesref{$log} }{$t});
|
|
$ntimes = $#times + 1;
|
|
|
|
printf $ics . "%2d ", $ntimes;
|
|
}
|
|
print "\n";
|
|
|
|
|
|
# ================
|
|
# Print High
|
|
printf " %-10s", "High:";
|
|
printf $ics . "%5.2f", $basehi;
|
|
|
|
foreach $log (@logfiles) {
|
|
@times = split(' ', ${ $timesref{$log} }{$t});
|
|
($hi, $lo, $tot) = ×_hilotot(@times);
|
|
|
|
if ($basehi && $hi) {
|
|
$pchg = 100.0 * ($hi - $basehi) / $basehi;
|
|
printf $ics . "%5.2f (%5.1f%%)", $hi, $pchg;
|
|
} else {
|
|
printf $ics . "%5.2f ( N/A )", $hi;
|
|
}
|
|
}
|
|
print "\n";
|
|
|
|
|
|
# ================
|
|
# Print Low
|
|
printf " %-10s", "Low:";
|
|
printf $ics . "%5.2f", $baselo;
|
|
|
|
foreach $log (@logfiles) {
|
|
@times = split(' ', ${ $timesref{$log} }{$t});
|
|
($hi, $lo, $tot) = ×_hilotot(@times);
|
|
|
|
if ($baselo && $lo) {
|
|
$pchg = 100.0 * ($lo - $baselo) / $baselo;
|
|
printf $ics . "%5.2f (%5.1f%%)", $lo, $pchg;
|
|
} else {
|
|
printf $ics . "%5.2f ( N/A )", $lo;
|
|
}
|
|
}
|
|
print "\n";
|
|
|
|
|
|
# ================
|
|
# Print Average
|
|
printf " %-10s", "Average:";
|
|
printf $ics . "%5.2f", $baseav;
|
|
|
|
foreach $log (@logfiles) {
|
|
@times = split(' ', ${ $timesref{$log} }{$t});
|
|
$av = &average(@times);
|
|
|
|
if ($baseav && $av) {
|
|
$pchg = 100.0 * ($av - $baseav) / $baseav;
|
|
printf $ics . "%5.2f (%5.1f%%)", $av, $pchg;
|
|
} else {
|
|
printf $ics . "%5.2f ( N/A )", $av;
|
|
}
|
|
}
|
|
print "\n";
|
|
|
|
|
|
# ================
|
|
# Print Standard Deviation
|
|
printf " %-10s", "St Dev:";
|
|
printf $ics . "%5.2f", $basestdev;
|
|
|
|
foreach $log (@logfiles) {
|
|
@times = split(' ', ${ $timesref{$log} }{$t});
|
|
$stdev = &standard_deviation(&average(@times), @times);
|
|
|
|
if ($basestdev && $stdev) {
|
|
$pchg = 100.0 * ($stdev - $basestdev) / $basestdev;
|
|
printf $ics . "%5.2f (%5.1f%%)", $stdev, $pchg;
|
|
} else {
|
|
printf $ics . "%5.2f ( N/A )", $stdev;
|
|
}
|
|
}
|
|
print "\n";
|
|
}
|
|
}
|
|
|
|
|
|
# Walk through the logfile. We find lines of the form
|
|
#
|
|
# $ Software Manager
|
|
# Startup time: 9527 milliseconds
|
|
# $ Capture Tool
|
|
# Startup time: 12786 milliseconds
|
|
# ...
|
|
# We gather test names and startup time values into the
|
|
# %timeslist array and return a reference to it.
|
|
#
|
|
# We also fill in the global %alltests array with all the
|
|
# test names across all the files. We'll use the keys of
|
|
# %alltests to drive the main output loop once all the
|
|
# logfiles have been read.
|
|
|
|
sub read_logfile {
|
|
local($logfile) = @_[0];
|
|
local(%timeslist, $test, $starttm, @stline, %trials);
|
|
|
|
open(logfile) || die "Can't open $logfile: $!\n";
|
|
|
|
logproc:
|
|
while (<logfile>) {
|
|
# new test name
|
|
if (/^\$\s/) {
|
|
chop; # kill \n
|
|
s/^\$\s*//;
|
|
$test = $_; # remember test name
|
|
next;
|
|
}
|
|
|
|
# grab the startup time for this test
|
|
if (/^Startup/) {
|
|
|
|
# If this test is in the list of tests we
|
|
# want to ignore for this report, skip it.
|
|
|
|
next if grep(/^\Q$test\E$/, @ignore_tests);
|
|
|
|
# If we only want to process a specified number
|
|
# of trials from the logfile (from cmdline -N option),
|
|
# stop processing logfile if any one test case
|
|
# reaches the limit.
|
|
|
|
last logproc if $ntrials && ++$trials{$test} > $ntrials;
|
|
|
|
@stline = split;
|
|
$starttm = $stline[2] / 1000;
|
|
|
|
# push on this time (if valid)
|
|
$timeslist{$test} .= ' ' . $starttm if $starttm < $TIMEOUT_TM;
|
|
|
|
# Remember test name in keys of global %alltests
|
|
$alltests{$test}++;
|
|
|
|
next;
|
|
}
|
|
}
|
|
close logfile;
|
|
|
|
return \%timeslist;
|
|
}
|
|
|
|
|
|
# pass over this list of times and
|
|
# calculate interesting items.
|
|
sub times_hilotot {
|
|
local($hitime, $lotime, $totime);
|
|
|
|
$totime = 0;
|
|
foreach $tm (@_) {
|
|
$hitime = $tm if $tm > $hitime;
|
|
$lotime = $tm if $tm < $lotime || !$lotime;
|
|
$totime += $tm;
|
|
}
|
|
|
|
return ($hitime, $lotime, $totime);
|
|
}
|
|
|
|
|
|
# compute average of list of numbers
|
|
sub average {
|
|
local($n, $total);
|
|
local($cnt) = $#_ + 1;
|
|
|
|
$total = 0;
|
|
foreach $n (@_) {
|
|
$total += $n;
|
|
}
|
|
return $cnt ? $total / $cnt : 0;
|
|
}
|
|
|
|
|
|
# standard_deviation($average, @numbers)
|
|
sub standard_deviation {
|
|
local($av) = shift;
|
|
local($n, $rsum, $resid);
|
|
local($cnt) = $#_ + 1;
|
|
|
|
return 0 if $cnt <= 1; # stdev for 0,1 samples?
|
|
|
|
# sum the residuals
|
|
$rsum = 0;
|
|
foreach $n (@_) {
|
|
$resid = $n - $av;
|
|
$rsum += $resid * $resid;
|
|
}
|
|
|
|
return sqrt($rsum / $cnt);
|
|
}
|