SysTutorials

How to Monitor Process I/O Utilization

Getting accurate I/O metrics per process is critical for troubleshooting performance issues, identifying storage bottlenecks, and capacity planning. Linux provides several tools for this task, each with different trade-offs between accuracy and overhead.

Using /proc/[pid]/io

The simplest approach is reading directly from the proc filesystem. Each process has an io file containing I/O statistics:

cat /proc/1234/io

Output looks like:

rchar: 1234567
wchar: 7654321
syscr: 456
syscw: 789
read_bytes: 2097152
write_bytes: 5242880
cancelled_write_bytes: 0

The relevant fields are:

To get current I/O rate, sample these values twice with a time interval:

#!/bin/bash
pid=$1
interval=${2:-1}

read_bytes_start=$(grep "^read_bytes" /proc/$pid/io | awk '{print $2}')
write_bytes_start=$(grep "^write_bytes" /proc/$pid/io | awk '{print $2}')
timestamp_start=$(date +%s%N)

sleep $interval

read_bytes_end=$(grep "^read_bytes" /proc/$pid/io | awk '{print $2}')
write_bytes_end=$(grep "^write_bytes" /proc/$pid/io | awk '{print $2}')
timestamp_end=$(date +%s%N)

elapsed=$(echo "scale=3; ($timestamp_end - $timestamp_start) / 1000000000" | bc)
read_rate=$(echo "scale=2; ($read_bytes_end - $read_bytes_start) / $elapsed / 1024 / 1024" | bc)
write_rate=$(echo "scale=2; ($write_bytes_end - $write_bytes_start) / $elapsed / 1024 / 1024" | bc)

echo "Read: ${read_rate} MB/s"
echo "Write: ${write_rate} MB/s"

Limitations: This approach doesn’t give you percentage utilization relative to disk capacity. It only shows throughput.

Using iotop

iotop is purpose-built for this task and shows actual disk I/O per process:

sudo iotop -o -b -n 1

Flags:

Output includes DISK READ, DISK WRITE, and IO% columns. The IO% represents the percentage of time the disk was busy servicing that process’s I/O requests.

For continuous monitoring:

sudo iotop -d 2 -o

This refreshes every 2 seconds showing only active processes.

Using pidstat

The pidstat tool from sysstat package provides flexible I/O reporting:

sudo pidstat -d -p 1234 1 10

This shows I/O stats for PID 1234, sampling every 1 second for 10 iterations. Output columns include:

For all processes with significant I/O:

sudo pidstat -d -u 1

eBPF-Based Approaches

For production environments requiring minimal overhead and kernel-level insights, eBPF tools are superior. These use in-kernel filtering to avoid expensive context switches:

sudo apt install bpftrace

A simple tracing script:

sudo bpftrace -e 'tracepoint:syscalls:sys_enter_read,
                   tracepoint:syscalls:sys_enter_write {
  @[comm] = count();
}'

This counts read/write syscalls by process name without overhead of context switching back to userspace.

For production-grade monitoring, tools like Cilium Hubble and Datadog provide eBPF-based I/O telemetry that’s far more efficient than traditional tools.

Practical Considerations

For containerized workloads, use cgroup v2 I/O limits and monitoring which integrate directly with container runtimes:

cat /sys/fs/cgroup/system.slice/docker-*.scope/io.stat

Choose your tool based on whether you need real-time interactivity (iotop), scriptable metrics (pidstat), or production-scale observability (eBPF platforms).

← All posts