Monitoring process memory/CPU usage with top and plotting it with gnuplot

siege-c3e2

If you want to monitor the memory and CPU usage of a particular Linux process for a few minutes, perhaps during a performance test, you can capture the data with top and plot them with gnuplot. Here is how:

Run this script (perhaps via nohup) to capture the data:


#!/bin/sh
##
## BEWARE: Check with your impl. of top what exactly it returns, it migth differ from mine
##
# Usage: ./monitor-usage.sh <PID of the process>
# Output: top.dat with lines such as `1539689171 305m 2.0`, i.e. unix time – memory with m suffix – CPU load in %
# To plot the output, see https://gist.github.com/holyjak/1b58dedae3207b4a56c9abcde5f3fdb5
export PID=$1
rm top.dat
while true; do top -p $PID -bn 1 -em | egrep '^ *[0-9]+' | awk -v now=$(date +%s.%N) '{print now,$6,$9}' >> top.dat; done
# top: -p <pid> target process, -b batch mode, -n 1 run once; -em display mem in MB
# egrep extracts the line starting with the pid, with the metrics
# awk prepends a date and extracts columns 6 (RES = residential memory, ie RAM) and 9, which should be the memory and cpu load

then plot them via ./usage-plot.gp top.dat top.png:


#!/usr/bin/env -S gnuplot –persist -c
# Plot memory and CPU usage over time. Usage:
# usage-plot.gp <input file> [<output .png file>]
# where the input file has the columns `<unix time> <memory, with m/g suffix> <% cpu>`
# To create the input file, see https://gist.github.com/jakubholynet/931a3441982c833f5f8fcdcf54d05c91
# Arguments:
infile=ARG1
outfile=ARG2
set term x11
set title 'Memory, CPU usage from' . infile
set xdata time
set timefmt "%s"
set xlabel "Time [[hh:]mm:ss]"
set ylabel "Memory usage"
set format y '%.1s%cB'
set y2label 'CPU usage'
set format y2 '%.0s%%'
set y2tics nomirror
set tics out
set autoscale y
set autoscale y2
# Credit: Christoph @ https://stackoverflow.com/a/52822256/204205
resolveUnit(s)=(pos=strstrt("kmgtp",s[strlen(s):*]), real(s)*(1024**pos))
if (exists("outfile") && strlen(outfile) > 0) {
print "Outputting to the file ", outfile
set term png # 640,480
set output outfile
}
# Styling
set style line 1 linewidth 2 linecolor 'blue'
set style line 2 linecolor 'light-green'
#set xtics font ", 10"
set tics font ", 10"
set xtics rotate 60 # put label every 60s, make vertical so they don't clash in .png if too many
plot infile u 1:3 with lp axes x1y2 title "cpu" linestyle 2, \
infile using 1:(resolveUnit(stringcolumn(2))) with linespoints title "memory" linestyle 1

view raw

plot-usage.gp

hosted with ❤ by GitHub

Published by Jakub Holý

I’m a JVM-based developer since 2005, consultant, and occasionally a project manager, working currently with Iterate AS in Norway.