Skip to content
Snippets Groups Projects
  • wierenga's avatar
    abcd4b2d
    %[BugId: 161]% · abcd4b2d
    wierenga authored
    Detection of process id of program under profiling control now copes
    with binaries that have been wrapped using wrapexec.
    abcd4b2d
    History
    %[BugId: 161]%
    wierenga authored
    Detection of process id of program under profiling control now copes
    with binaries that have been wrapped using wrapexec.
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)"