Skip to content

Instantly share code, notes, and snippets.

@nicolasazrak
Last active January 12, 2024 21:24
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save nicolasazrak/32d68ed6c845a095f75f037ecc2f0436 to your computer and use it in GitHub Desktop.
Save nicolasazrak/32d68ed6c845a095f75f037ecc2f0436 to your computer and use it in GitHub Desktop.
Graph process memory

Usage ./graph.sh

It requires having gnuplot installed

#!/bin/env bash
# https://stackoverflow.com/questions/7998302/graphing-a-processs-memory-usage
# trap ctrl-c and call ctrl_c()
trap ctrl_c INT
LOG=$(mktemp)
SCRIPT=$(mktemp)
IMAGE=$(mktemp)
echo "Output to LOG=$LOG and SCRIPT=$SCRIPT and IMAGE=$IMAGE"
cat >$SCRIPT <<EOL
set term png small size 800,600
set output "$IMAGE"
set ylabel "RSS"
set y2label "VSZ"
set ytics nomirror
set y2tics nomirror in
set yrange [0:*]
set y2range [0:*]
plot "$LOG" using 3 with lines axes x1y1 title "RSS", "$LOG" using 2 with lines axes x1y2 title "VSZ"
EOL
function ctrl_c() {
gnuplot $SCRIPT
xdg-open $IMAGE
exit 0;
}
while true; do
ps -p $1 -o pid=,vsz=,rss= | tee -a $LOG
sleep 1
done
@will3216
Copy link

If you replace:

ps -p $1 -o pid=,vsz=,rss= | tee -a $LOG

with:

ps -p $1 -o pid= -o vsz= -o rss= | tee -a $LOG

It will work out of the box with more systems. Thanks for making this!

@bmarchant
Copy link

Great work. I made a few changes for some things I am working on and here are the results:

graph_memory

I found that ps -p required the PID so I used pidof to get that. I added waiting so you can fire off the script before the executable runs and it will wait for it before beginning to log. Also added a command line argument for saving out the output file to somewhere other than mktemp. I removed tee and used output redirection because tee output to both standard out and to the log file, just to clean things up. Also the loop ends, not on ctrl-C but when the executable finishes running so that the whole lifetime is represented in the plot. Also implemented @will3216's suggestion because -o pid=,vsz=,rss= didn't work for me on CentOS 7 so I used the more generic syntax. Then I cleaned up the plot and used the same scale for both Real Memory and Virtual Memory and used the colors from htop.

#!/bin/env bash

# https://stackoverflow.com/questions/7998302/graphing-a-processs-memory-usage
# https://gist.github.com/nicolasazrak/32d68ed6c845a095f75f037ecc2f0436

if [ $# -lt 1 ] || [ $# -gt 2 ]
then
  echo "graph_memory.sh requires 1 or 2 command line arguments"
  echo "Usage:"
  echo "     graph_memory.sh <process name> [PNG image path]"
  exit -1
fi

LOG=$(mktemp)
SCRIPT=$(mktemp)
if [ $# -eq 1 ]
then
  IMAGE=$(mktemp)
else
  IMAGE=$2
fi

echo "Output to LOG=$LOG and SCRIPT=$SCRIPT and IMAGE=$IMAGE"

cat >$SCRIPT <<EOL
set term png small size 1200,900
set output "$IMAGE"
set key left box
set ylabel "Memory (MB)"
set xlabel "Seconds"

set grid ytics lc rgb "#bbbbbb" lw 1 lt 0
set grid xtics lc rgb "#bbbbbb" lw 1 lt 0

set ytics nomirror
set yrange [0:*]

plot "$LOG" using (\$2/1024) with filledcurves title "Virtual Memory" lc rgb "#00bf9b0b", "$LOG" using (\$3/1024) with filledcurves title "Real Memory" lc rgb "#004d950f"

EOL

echo "Waiting for $1 to start..."

PID=`pidof $1`
while [ -z $PID ]
do
  sleep 0.1
  PID=`pidof $1`
done

echo "Logging $1 info..."

SAVE_PID=$PID
#echo "$SAVE_PID 0 0" >> $LOG
echo "$SAVE_PID 0 0" >> $LOG

while true
do
  # Drop out when the process doesn't exist anymore
  if [ -z $PID ]
  then
    echo "Rendering graph..."
    echo "$SAVE_PID 0 0" >> $LOG
    gnuplot $SCRIPT > /dev/null
    xdg-open $IMAGE > /dev/null &
    exit 0
  fi
  # Log the process information
  ps -p $PID -o pid= -o vsz= -o rss= >> $LOG
  sleep 1
  PID=`pidof $1`
done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment