lathist.prl 3.04 KB
#!/usr/local/bin/perl5 -w
#
# Copyright (C) 1996-1998 by the Board of Trustees
#    of Leland Stanford Junior University.
# 
# This file is part of the SimOS distribution. 
# See LICENSE file for terms of the license. 
#

#
#  Generate a simple autoscaling histogram of the length of an
#  interval between two log annotation labels.
#
#  args   start_label  end_label  [matchsymbol]  [logfile name]
#
#  The labels can be anywhere on the LOG line.
#  If the matchsymbol is present, it chucks out any lines which
#  don't match.  I use this to restrict to a single process.
#


die if $#ARGV < 1;

$startsymbol = $ARGV[0];
$endsymbol = $ARGV[1];
if ($#ARGV > 1) {
    $matchsymbol = $ARGV[2];
} else {
    $matchsymbol = "";
}

if ($#ARGV > 2) {
    $fname = $ARGV[3];
} else {
    $fname = "./cpu.log";
}

open (CPULOG, $fname);


$expectingstart = 1;
$callnum = 0;
$totlat = 0;

while (<CPULOG>) {
    $line = $_;
    next if ! /^LOG/o;
    if ($matchsymbol) { next if ! /$matchsymbol/o; } 

    if (/$startsymbol/o) {
        if (! $expectingstart) {
            print "Warning unexpected function start at line ", $., "\n";
        }
        $line =~ /^LOG (\d+)/;
        $startcycle = $1;
        $expectingstart = 0;
    } elsif (/$endsymbol/o) {
        if ($expectingstart) {
            print "Warning unexpected function end at line ", $., "\n";
        } else {
            $line =~ /^LOG (\d+)/;
            $expectingstart = 1;
            $latency[$callnum] = $1 - $startcycle;
            $totlat += $latency[$callnum];
            $callnum++;
        }
    }
}

sub bynumber {$a <=> $b; }
@sortedlats = sort bynumber @latency;
print "range from $startsymbol to $endsymbol";
if ($matchsymbol) {print " when line includes $matchsymbol";}
print "\n";
print "num ranges = ", $#sortedlats+1, "\n";
printf "average latency = %.2f cycles\n", $totlat / $callnum;


$nbuckets = 30;

$minval = $sortedlats[0];
$maxval = $sortedlats[$#sortedlats];

print "min = ", $minval, "\n";
print "max = ", $maxval, "\n";

$ival = ($maxval - $minval) / $nbuckets;

# round ival up to nearest x * 10^n value where x in 1..9 
$logten = int(log($ival) / log(10));
$base = exp($logten * log(10));
$ival = $base * (int($ival/$base)+1);

# initial bucket always empty
$cbucket = $ival * int($minval/$ival);

$j = 0;
$maxsize = 0;

for ($i=0; $i<$nbuckets && $j <= $#sortedlats; $i++) {
    $count = 0;
    while ($sortedlats[$j] < $cbucket) {
        $count++;
        $j++;
        last if ($j > $#sortedlats);
    }
    $bucketsize[$i] = $count;
    $bucketlabel[$i] = $cbucket;
    if ($bucketsize[$i] > $maxsize) {
        $maxsize = $bucketsize[$i];
    }
    $cbucket += $ival;
}

$lastbucket = $i-1;
$ovflwsize = $#sortedlats - $j + 1;
if ($ovflwsize > $maxsize) {
    $maxsize = $ovflwsize;
}

$xscale = int($maxsize/60)+1;

print "Each * represents up to $xscale occurrences\n\n";

for ($i=0; $i<=$lastbucket; $i++) {
    printf "%8d %s\n", $bucketlabel[$i], "*" x (1+(($bucketsize[$i]-1)/$xscale));
}
printf "%8s %s\n", "ovflw", "*" x (1+(($ovflwsize - 1)/$xscale));

print "\n";

# print join(' ', @sortedlats);