#! /usr/bin/perl
# -*- Mode: perl; -*-
#
# In Progress script to make the default log files more readable.
# This indents the routine enter/exit lines, and applies that indent to
# other lines. It also simplifies the lines, removing all but the message
# and location (and computing the time within each function)
#
# Set defaults
my $whichrank = -1;
my $filenameTrim = "default";
my %elideCall = ();
my $infile = "";
my $isThreaded = 1;
my $onlyRoutine = 0;
for (@ARGV) {
if (/^--?rank=(\d+)/) {
$whichrank = $1;
}
elsif (/^--?srcdir=(.*)/) {
$filenameTrim = $1;
}
elsif (/^--?elide=(.*)/) {
# This must exactly match the function name recorded
$elideCall{$1} = 1;
$elideCall{"MPID_STATE_$1"} = 1;
}
elsif (/^-/) {
print STDERR
"getfuncstack [ -rank=n ] [-srcdir=path] [-elide=name] < logfile\n";
exit(1);
}
else {
$infile = $_;
break;
}
}
@ARGV = ();
# Set initial values
my $linecount = 0;
my $nestlevel = 0;
my $curstate = "";
my @routineStack = ();
my @routineTime = ();
my $inElide = 0;
while (<>) {
my $spaces = "";
my $tottime = "";
my $extraMsg = "";
$linecount++;
($world,$rank,$thread,$class,$time,$file,$line,$msg) = split( /\t/, $_ );
# # Check for validity
# Removed for now - best to use on separate file output
# if ((!$isThreaded && $thread != 0) || $class < 0) {
# # These should really be checks for is-int as well
# next;
# }
# Discard unwanted ranks
if ($whichrank >= 0 && ($rank != $whichrank || $world > 0) ) { next; }
# Automatically choose the default filename trim
if ($filenameTrim eq "default") {
$filenameTrim = $file;
$filenameTrim =~ s/(.*\/mpich[^\/]*\/src\/).*/\1/;
}
if ($filenameTrim ne "" && $file =~ /^$filenameTrim/) {
$file =~ s/^$filenameTrim//;
}
# Update nesting level
if ($msg =~ /^Entering (.*)/) {
$curstate = $1;
if (defined($elideCall{$curstate})) {
$inElide = 1;
}
elsif (!$inElide) {
$spaces = &indent($nestlevel++) . ">";
$routineStack[$#routineStack+1] = $curstate;
$routineTime[$#routineTime+1] = $time;
}
}
elsif ($msg =~ /^Leaving (.*)/) {
$curstate = $1;
if ($nestlevel > 0) {
if (defined($elideCall{$curstate})) {
$inElide = 0;
}
elsif (!$inElide) {
$spaces = &indent(--$nestlevel) . "<";
my $expected = $routineStack[$#routineStack];
$#routineStack--;
if ($expected ne $curstate) {
print STDERR "Expected state $expected but found $curstate\n";
}
# Get the total time in this routine
$tottime = $time - $routineTime[$#routineTime];
$#routineTime--;
# Round totaltime to a few digits
$tottime = sprintf("%.3g",$tottime);
$tottime = "($tottime)";
}
}
}
else {
if ($onlyRoutine) {
print STDERR "Malformed line $linecount: $_";
next;
}
$spaces = &indent($nestlevel);
$extraMsg = $msg;
$extraMsg =~ s/\r?\n//;
}
# Strip common text off of state
$curstate =~ s/^MPID_STATE_//;
$curstate =~ s/\r?\n//g;
if (! $inElide) {
my $baseinfo = $spaces;
if ($extraMsg ne "") {
$baseinfo .= $extraMsg;
}
else {
$baseinfo .= $curstate . "$tottime";
}
my $location = "$file\[$line\]";
my $pad = 40 - length($baseinfo);
for (my $i=0; $i<$pad; $i++) { $baseinfo .= " "; }
print "$baseinfo $location\n";
}
}
sub indent {
my $num = $_[0];
my $spaces = "";
for (my $i=0; $i<=$num; $i++) {
$spaces .= " ";
}
return $spaces;
}