#! @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; }