1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
#! /usr/bin/perl
##
## Copyright (C) by Argonne National Laboratory
## See COPYRIGHT in top-level directory
##
# 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;
}
|