Skip to content

Instantly share code, notes, and snippets.

@jhinrichsen
Created April 12, 2018 12:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jhinrichsen/a1cca21379c58100ec9b0db72263000a to your computer and use it in GitHub Desktop.
Save jhinrichsen/a1cca21379c58100ec9b0db72263000a to your computer and use it in GitHub Desktop.
Linux: plot threads and processes usage over time (see related Gist 'threads')
package main
import (
"bufio"
"flag"
"image/color"
"io"
"log"
"os"
"strconv"
"strings"
"time"
"gonum.org/v1/plot"
"gonum.org/v1/plot/plotter"
"gonum.org/v1/plot/vg"
)
type Value struct {
T time.Time
nPids int
nTids int
}
func die(err error) {
if err != nil {
log.Fatal(err)
}
}
func lines(source string) []string {
var input io.Reader
if len(source) == 0 {
input = os.Stdin
} else {
i, err := os.Open(source)
die(err)
input = i
}
var lines []string
scanner := bufio.NewScanner(input)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
return lines
}
func parse(lines []string) []Value {
var vs []Value
for _, line := range lines {
cols := strings.Split(line, "\t")
t, err := time.Parse(time.RFC3339, cols[0])
die(err)
n1, err := strconv.Atoi(cols[3])
die(err)
n2, err := strconv.Atoi(cols[5])
die(err)
vs = append(vs, Value{t, n1, n2})
}
return vs
}
func main() {
source := flag.String("source", "",
"standard input if empty input file")
flag.Parse()
values := parse(lines(*source))
pidPts := make(plotter.XYs, len(values))
tidPts := make(plotter.XYs, len(values))
for i := range values {
pidPts[i].X = float64(values[i].T.Unix())
pidPts[i].Y = float64(values[i].nPids)
tidPts[i].X = float64(values[i].T.Unix())
tidPts[i].Y = float64(values[i].nTids)
}
p, err := plot.New()
if err != nil {
log.Fatal(err)
}
p.Title.Text = "Time Series"
p.X.Tick.Marker = plot.TimeTicks{Format: "2006-01-02\n15:04"}
p.Y.Label.Text = "Number"
p.Add(plotter.NewGrid())
// pidLine, pidPoints, err := plotter.NewLinePoints(pidPts)
pidLine, _, err := plotter.NewLinePoints(pidPts)
if err != nil {
log.Fatal(err)
}
pidLine.Color = color.RGBA{G: 255, A: 255}
// pidPoints.Shape = draw.CircleGlyph{}
// pidPoints.Color = color.RGBA{R: 255, A: 255}
// tidLine, tidPoints, err := plotter.NewLinePoints(tidPts)
tidLine, _, err := plotter.NewLinePoints(tidPts)
if err != nil {
log.Fatal(err)
}
tidLine.Color = color.RGBA{B: 255, A: 255}
// tidPoints.Shape = draw.CircleGlyph{}
// tidPoints.Color = color.RGBA{R: 255, A: 255}
p.Add(pidLine, tidLine)
p.Legend.Add("Processes", pidLine)
p.Legend.Add("Threads", tidLine)
// DIN A4
err = p.Save(29.7*vg.Centimeter, 21*vg.Centimeter, "threads.svg")
if err != nil {
log.Fatal(err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment