Skip to content

Instantly share code, notes, and snippets.

@emilong
Forked from bisrael8191/process_graph.sh
Created August 26, 2021 18:49
Show Gist options
  • Save emilong/647d3625f29b2dd55006c6cd5ac6ec5d to your computer and use it in GitHub Desktop.
Save emilong/647d3625f29b2dd55006c6cd5ac6ec5d to your computer and use it in GitHub Desktop.
Log and graph peformance metrics on a single process
#!/bin/bash
# Log and graph peformance metrics on a single process
# Based on: http://brunogirin.blogspot.com.au/2010/09/memory-usage-graphs-with-ps-and-gnuplot.html
#
# Requires gnuplot to be installed and on your path.
#
# Run: ./process_graph [process name] [pid]
DEFAULT_PROCNAME="Xorg"
PROCNAME=${1:-$DEFAULT_PROCNAME}
PID=${2:-`pidof $PROCNAME`}
NUMCPU=$(cat /proc/cpuinfo | grep processor | wc -l)
TIMEOUT=1
NUMTIMES=60
if [ -z $PID ]; then
echo "PID for $PROCNAME not found, try manually specifying it"
exit
fi
echo "Watching the $PROCNAME [$PID] process for $[TIMEOUT*NUMTIMES] seconds..."
# Calculate the total %CPU usage over the period since
# the function was last called.
previdle=0
prevtotal=0
TOTALCPU=0
DIFF=0
calcTotalCpu() {
# Read the current cpu values from the stat file
read cpu user nice sys curidle rest < /proc/stat
curtotal=$[user+nice+sys+curidle]
# If this isn't the first time this function has been called,
# calculate the total %CPU since the previous time
if [ "$prevtotal" -ne "0" ]; then
DIFF=$[curtotal-prevtotal]
TOTALCPU=$(echo "scale=2; 100*(($curtotal-$prevtotal) - ($curidle-$previdle)) / ($curtotal-$prevtotal)" | bc)
fi
# Store the current idle and total times for the next time
previdle=$curidle
prevtotal=$curtotal
}
# Calculate the total %CPU usage for a PID over the period since
# the function was last called.
prevpidtotal=0
PIDCPU=0
calcPidCpu() {
# Read the current PID cpu values from the stat file
curpidtotal=`cat /proc/${PID}/stat | awk '{t = $14 + $15; print t}'`
# Calculate the PID's CPU usage
if [ "$DIFF" -ne 0 ]; then
PIDCPU=$(echo "scale=2; ($NUMCPU * ($curpidtotal-$prevpidtotal) * 100) / $DIFF" | bc)
fi
# Store the current PID total for the next time
prevpidtotal=$curpidtotal
}
#
# Main script
#
# Remove old log
rm -rf ${PROCNAME}_perf.log
# Loop for the user defined duration/period and log metrics
for i in `seq 1 $NUMTIMES`; do
# Calculate CPU usage
calcTotalCpu
calcPidCpu
# Get memory usage
PIDMEM=`ps -p $PID -o %mem=`
# If all values were calculated, output to log file
if [ $(echo "$PIDCPU != 0" | bc -l) == 1 ]; then
echo "${PIDCPU}${PIDMEM}" >> ${PROCNAME}_perf.log
fi
sleep $TIMEOUT
done
# Use gnuplot to convert the log file to a graph
echo "Plotting graph to ${PROCNAME}_graph.png"
gnuplot <<- EOF
set term png small size 800,600
set output "${PROCNAME}_graph.png"
set title "${PROCNAME} Performance"
set xlabel "Time (sec)"
set ylabel "%CPU" textcolor rgb "red"
set y2label "%MEM" textcolor rgb "green"
set ytics nomirror textcolor rgb "red"
set y2tics nomirror in textcolor rgb "green"
set yrange [0:*]
set y2range [0:*]
plot "${PROCNAME}_perf.log" using 1 with lines linewidth 3 axes x1y1 title "%CPU", \
"${PROCNAME}_perf.log" using 2 with lines linewidth 3 axes x1y2 title "%MEM"
EOF
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment