-
-
Save emilong/647d3625f29b2dd55006c6cd5ac6ec5d to your computer and use it in GitHub Desktop.
Log and graph peformance metrics on a single process
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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