Skip to content

supakeen/pgr

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pgr

A Linux utility to graph resource usage of a process and its subprocesses over time. It uses procfs to record memory, CPU, I/O, thread, and file descriptor metrics for a process tree, outputting timestamped snapshots in JSON Lines format. Recordings can be visualized as terminal line charts or summary tables.

Requirements

  • Linux kernel >= 3.5 (uses /proc/[pid]/task/[tid]/children for subprocess discovery)
  • Go 1.26+

Installation

go install github.com/supakeen/pgr/cmd/pgr@latest

Or build from source:

git clone https://github.com/supakeen/pgr.git
cd pgr
go build ./cmd/pgr

Usage

Recording

Record resource usage of a process and all its descendants:

pgr record --pid <PID>

Options:

Flag Short Default Description
--pid -p Root process ID to monitor (required)
--interval -i 1s Sampling interval (Go duration)
--output -o stdout Output file path
--long-names -l false Use full command name from /proc/[pid]/cmdline instead of the kernel 15-char comm name

Examples:

# Record PID 1234 every second to stdout
pgr record -p 1234

# Record every 500ms to a file
pgr record -p 1234 -i 500ms -o recording.jsonl

# Record with full command names
pgr record -p 1234 -l

# Record every 5 seconds
pgr record -p 1234 -i 5s

Stop recording with Ctrl-C (SIGINT) or SIGTERM. Recording also stops automatically when the root process exits.

Output format

Output is JSON Lines — one JSON object per line, one line per sample. Each sample contains a timestamp and resource stats for every process in the tree at that point in time:

{
  "timestamp": "2026-05-15T10:30:00.123Z",
  "processes": [
    {
      "pid": 1234,
      "ppid": 1233,
      "name": "myapp",
      "vm_size_kb": 67890,
      "vm_rss_kb": 12345,
      "shared_kb": 1000,
      "swap_kb": 0,
      "utime_ticks": 500,
      "stime_ticks": 200,
      "read_bytes": 4096000,
      "write_bytes": 2048000,
      "threads": 4,
      "fd_count": 12
    }
  ]
}
Field Source Description
vm_size_kb /proc/[pid]/status Virtual memory size (kB)
vm_rss_kb /proc/[pid]/status Resident set size — physical memory (kB)
shared_kb /proc/[pid]/status Shared memory / RssShmem (kB)
swap_kb /proc/[pid]/status Swapped memory (kB)
utime_ticks /proc/[pid]/stat CPU time spent in user mode (clock ticks)
stime_ticks /proc/[pid]/stat CPU time spent in kernel mode (clock ticks)
read_bytes /proc/[pid]/io Bytes read from storage
write_bytes /proc/[pid]/io Bytes written to storage
threads /proc/[pid]/status Number of threads
fd_count /proc/[pid]/fd/ Number of open file descriptors

Note: /proc/[pid]/io requires the reader to be the same user as the process (or have CAP_SYS_PTRACE). If unreadable, read_bytes and write_bytes will be 0.

Drawing charts

Render a recording as a terminal line chart:

pgr draw <file>
pgr draw -    # read from stdin (live mode)

Options:

Flag Short Default Description
--metric -m rss Metric to plot (see below)
--no-total false Hide the aggregate total line
--no-per-process false Hide individual process lines
--height -H auto Chart height in terminal rows
--human-readable -r false Show y-axis values in human-readable format
--top -n 0 (all) Show only the top N processes by peak usage
--group -g false Group processes by name (sum values for same-name PIDs)
--timespan -t 0 (all) Only show the last duration of data (e.g. 30s, 5m)

Examples:

# Draw RSS chart from a file
pgr draw recording.jsonl

# Live chart piped from record
pgr record -p 1234 | pgr draw -

# CPU ticks chart with human-readable axis, top 5 processes
pgr draw recording.jsonl -m cpu -r -n 5

# I/O bytes chart, grouped by process name
pgr draw recording.jsonl -m io -r -g

# Thread count over time
pgr draw recording.jsonl -m threads

# Only the last 2 minutes
pgr draw recording.jsonl -t 2m

Tables

Render a summary table of process tree resource usage:

pgr table <file>
pgr table -    # read from stdin (live mode)

Options:

Flag Short Default Description
--metric -m rss Metric to display (see below)
--human-readable -r false Show values in human-readable format
--top -n 0 (all) Show only the top N processes by peak usage
--group -g false Group processes by name (sum values for same-name PIDs)

The table shows each process with its runtime, average, and peak value for the selected metric. In the default (non-grouped) mode, processes are displayed as a tree reflecting the parent-child hierarchy.

Examples:

# RSS table from a file
pgr table recording.jsonl

# Human-readable memory table, top 10
pgr table recording.jsonl -r -n 10

# Thread count table grouped by name
pgr table recording.jsonl -m threads -g

# FD count table
pgr table recording.jsonl -m fds -r

# Live table piped from record
pgr record -p 1234 | pgr table -

Available metrics

Name Description Unit
rss Resident set size (default) kB
vmsize Virtual memory size kB
shared Shared memory kB
swap Swap usage kB
cpu Total CPU time (user + system) ticks
utime User-mode CPU time ticks
stime System-mode CPU time ticks
io Total I/O (read + write) bytes
read_bytes Storage bytes read bytes
write_bytes Storage bytes written bytes
threads Thread count count
fds Open file descriptor count count

An unknown --metric value will produce an error.

In live mode (draw -), when --timespan is set, old samples outside the window are discarded to keep memory usage bounded.

Version

pgr version

Building with version info

Pass version and commit at build time via ldflags:

go build -ldflags "-X main.version=1.0.0 -X main.commit=$(git rev-parse --short HEAD)" ./cmd/pgr

License

See LICENSE.

About

Go executable to visualize process memory, IO, or others over time.

Resources

License

Stars

Watchers

Forks

Contributors