Code owners
Assign users and groups as approvers for specific file changes. Learn more.
profiletool 4.98 KiB
#!/bin/sh
# use -x option on sh to enable trace debuggin
# profiletool: shell script to perform a profiling run of a binary
#
# Copyright (C) 2003
# ASTRON (Netherlands Foundation for Research in Astronomy)
# P.O.Box 2, 7990 AA Dwingeloo, The Netherlands, seg@astron.nl
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
# check arguments
if test $# -lt 2; then
echo "usage: profiletool binname command [args]"
echo " profiletool produces a directory '<binname>.profile.dir.X' and"
echo " a tgz version as '<binname>.profile.dir.X.tgz'."
exit 1
fi
# get targetbinary name
binname=$1;
shift;
# get binary name
command=$1;
cmdbase=`basename $command`;
shift;
#
# all profiling output goes into profile directory
# find new name for this run
#
alldirs=`ls -1 | grep "^$binname.profile.dir.[[:digit:]]\+$" | cut -d. -f4 | sort -n | tail -1`;
if test "$alldirs" = ""; then
profdir="$binname.profile.dir.1";
else
declare -i seqnr=`echo $alldirs | sed -e 's/$binname\.//' | cut -d. -f4`;
seqnr=$seqnr+1;
profdir="$binname.profile.dir.$seqnr";
fi
mkdir $profdir
# register start time
echo -n "START " > $profdir/epoch
date >> $profdir/epoch
# save compiler command if it exists
if test -f $target.compile.log; then
cp $target.compile.log $profdir/compile.log
fi
# save command
echo $command $* > $profdir/cmdline 2>&1
# save various aspects of machine state
uname -a > $profdir/uname 2>&1
cat /proc/cpuinfo > $profdir/cpuinfo 2>&1
# save information on shared libraries used by the binary
echo "output of 'ldd -v -d -r $binname'" > $profdir/ldd.out 2>&1
ldd -v -d -r $binname >> $profdir/ldd.out 2>&1
#
# save meminfo before running program
#
echo > $profdir/meminfo
echo "START" >> $profdir/meminfo
cat /proc/meminfo >> $profdir/meminfo
#
# save loadavg statistics before running program
#
echo -n "START " > $profdir/loadavg
cat /proc/loadavg >> $profdir/loadavg 2>&1
#
# Do single top before starting command
#
top -b -n1 > $profdir/top.log 2>&1
#
# EXECUTE THE COMMAND
#
/usr/bin/time -o $profdir/time.out $command $* > $profdir/stdout 2> $profdir/stderr &
timepid=$!;
# wait some time before
sleep 5;
#
# find $binname pid, the loop is needed because it may not have started yet
# wait a maximum of 5 seconds to prevent hang when command doesn't start
#
declare -i progpid=0;
declare -i loopcount=0;
while test \( $progpid -eq 0 \) -a \( $loopcount -lt 5 \); do
sleep 1
# pstree -np $timepid 2> /dev/null
declare -i progpid=`pstree -np $timepid 2> /dev/null | sed -e "s/^.*$binname.*(\([[:digit:]]\+\)).*$/\1/"`;
loopcount=$loopcount+1;
done
# start top trace every 5 seconds
toppid=0;
if test $progpid -ne 0; then
top -b -p $progpid -d 5 >> $profdir/top.log 2>&1 &
toppid=$!;
fi
#
# cleanup function
#
function killproc()
{
for p in $*; do
if test $p -ne 0; then
kill $p > /dev/null 2>&1
fi
done
}
#
# install traps to clean up properly
#
trap "killproc $progpid;" SIGCHLD
trap "killproc $progpid $toppid; killall -9 $command > /dev/null 2>&1" EXIT
# wait for completion of program
wait $timepid > /dev/null 2>&1;
retcode=$?;
if test $retcode -ne 0; then
# log to epoch file
echo -n "FAIL (retcode=$retcode) " >> $profdir/epoch
date >> $profdir/epoch
# show problem to the user
tail $profdir/stderr
echo -n "FAIL (retcode=$retcode) "
date
fi
killproc $toppid;
wait $toppid > /dev/null 2>&1;
#
# Do single top after command has finished
#
top -b -n1 >> $profdir/top.log 2>&1
#
# Load average after command completes
#
echo -n "STOP " >> $profdir/loadavg
cat /proc/loadavg >> $profdir/loadavg
#
# save meminfo after running program
#
echo >> $profdir/meminfo
echo "STOP" >> $profdir/meminfo
cat /proc/meminfo >> $profdir/meminfo 2>&1
#
# produce gprof output
#
if test -f gmon.out; then
cp gmon.out $profdir
gprof -b $binname $profdir/gmon.out > $profdir/gprof.out 2>&1
fi
#
# copy clog or slog file when it exists
#
if test -f $binname.clog; then
cp $binname.clog $profdir/mpe.clog;
# convert to slog
(cd $profdir && $MPIBIN/clog2slog -f 128 mpe.clog);
fi
if test -f $binname.slog; then
cp $binname.slog $profdir/mpe.slog;
fi
# gzip profile dir
tar zcvf $profdir.tgz $profdir > /dev/null 2>&1
# log end
echo -n "STOP " >> $profdir/epoch
date >> $profdir/epoch
#
# bye bye
#
echo "profiletool: profile saved in $profdir (and compressed into $profdir.tgz)"