WIUNIX ACADEMY
Linux I/O latency: connect iostat, PSI and service pressure
Page 2 of 3. Review the earlier steps and prerequisites before continuing.
YOUR SYSTEM. YOUR STEPS.
Where are you working?
Choose your OS and version. The prerequisites, commands and troubleshooting follow your environment.
USE YOUR OWN VALUES
Configure this tutorial
Set the example values for your environment; related explanations and copy panels update together. Never enter passwords, private keys or tokens. Values stay in this tab and are not sent to the server or share links. Check actual DNS, certificates and network policy before running commands.
Different IP addresses, domains or ports? Open the settings below, change the values and select “Apply to tutorial”, then copy the updated commands.
Set values for my environment4 editable values
LET’S BUILD
Separate paging and blocked work from CPU usage
Use vmstat for the same incident period. Rate and CPU columns in its first data row are averages since boot; read the following rows for interval comparisons. Process and memory fields are instantaneous in every row. Look at blocked tasks, swap-in/swap-out and CPU fields together. The wa column is CPU idle time associated with outstanding I/O, not the percentage of application time lost to I/O.
A workload may stall on I/O while other tasks keep CPUs busy, leaving wa small. Memory reclaim and swapping can create storage traffic without a new database read surge. These signals support a hypothesis; they do not identify an individual disk or authorize changing swap, cache or kernel writeback settings.
Authorized terminal on the affected Linux host
date -u +%FT%TZ
LC_ALL=C vmstat 1 6The five interval rows after the initial summary are interpreted alongside pressure and device reports; paging is kept distinct from application I/O.
LET’S BUILD
Find candidate processes without exposing their arguments
pidstat samples task-accounted reads and writes. This panel uses process names rather than full command-line arguments, which may contain private values. A process with high write accounting is a candidate owner, not proof that every device request completed synchronously for that PID: buffered writeback and shared filesystems complicate attribution.
Zero or absent iodelay is inconclusive when task delay accounting is unavailable or disabled. The sysstat FAQ documents the kernel accounting requirements. Do not enable delay accounting or broaden procfs access as an incident shortcut. Resolve visibility with the host owner and keep the documented blind spot in the incident record.
Authorized terminal on the affected Linux host
date -u +%FT%TZ
LC_ALL=C pidstat -d -p ALL 1 5A bounded list of candidate PIDs is available within current permissions. Missing accounting and buffered-write attribution limits remain explicit.
LET’S BUILD
Optional: locate the existing service cgroup
Set example to the existing systemd service basename, without the .service suffix. Inspect its identity and ControlGroup before using a cgroup path. This optional branch requires cgroup v2 and host-level access; it does not create or move cgroups. A container’s private cgroup namespace may not expose the host path.
Combine the actual cgroup2 mount point with the returned ControlGroup and put that existing absolute directory into /sys/fs/cgroup/system.slice/example.service. The initial example is intentionally not a discovered service. A missing unit or empty ControlGroup means stop this branch, not copy a guessed directory.
Authorized terminal on the affected Linux host
systemctl show 'example.service' -p Id -p LoadState -p ActiveState -p MainPID -p ControlGroup
findmnt -t cgroup2 -o TARGET,FSTYPE,OPTIONSAn existing unit and its actual cgroup v2 directory are identified before cgroup counters are read; unavailable scopes are skipped.
LET’S BUILD
Compare service pressure, bytes and configured limits
Read the discovered service directory twice. io.stat counts bytes and operations by major:minor; compare each device’s delta over the same interval and map it back to lsblk. io.max can reveal a configured ceiling. A max entry does not prove that the service reached that ceiling, and absence of a local cap does not exclude a limit at a parent cgroup or storage provider.
Service-level pressure can be high while the host looks comfortable. Inspect the relevant ancestor policy with the service owner if needed; do not change io.max, io.weight or controller delegation to make numbers improve. Some kernels or cgroup arrangements do not expose every file; missing interfaces are not zeros.
Authorized terminal on the affected Linux host
(
set -eu
cg='/sys/fs/cgroup/system.slice/example.service'
test -d "$cg"
test "$(findmnt -n -o FSTYPE --target "$cg")" = cgroup2
for sample in 1 2; do
date -u +%FT%TZ
for name in io.pressure io.stat io.max memory.pressure; do
printf '\n%s\n' "$name"
if test -r "$cg/$name"; then cat "$cg/$name"; else printf 'unavailable or unreadable\n' >&2; fi
done
if test "$sample" = 1; then sleep 5; fi
done
)Two samples preserve device counters, service stalls and visible policy. Parent/provider limits and missing interfaces remain open questions.
Choose a next action from a consistent explanation
If application latency, I/O pressure and device queue/await rise together under comparable demand, investigate that storage path and backend limits or errors. If pressure is concentrated in one service with comfortable host devices, investigate its cgroup hierarchy and workload pattern. If memory pressure and swap rise first, investigate working-set growth and memory limits before buying faster disks.
If request latency worsens but these measurements stay normal, preserve the negative finding and investigate application locks, remote dependencies or CPU scheduling instead. Short samples can miss bursts; repeat a bounded window at the actual failure time rather than declaring an unrelated idle period a pass.
Choose one owner-approved mitigation at a time: for example reduce a restartable batch job’s concurrency through its own scheduler, or reschedule it outside the foreground peak. Preserve the previous application setting and backlog/replay plan. Throttling, pausing or retrying work can change completion time and data freshness; it is a workload decision, not a generic shell repair.
When the measurements do not line up
Use the matching diagnostic below and retain errors. Do not install a load generator, clear caches, change the I/O scheduler, disable MAC protection or reboot a production host to make an observation available.
PSI is missing or unreadable
Check the running kernel and visible interface. A container mount, kernel configuration or boot policy can hide/disable PSI. Record unavailable coverage and ask the host owner; do not treat this as zero pressure.
uname -r
ls -ld /proc/pressure
ls -l /proc/pressure/io /proc/pressure/memoryiostat does not show the expected device
Recheck the actual filesystem and block stack. Remote filesystems, overlays or a different namespace do not necessarily map to the device you guessed; kernel statistics can also be unavailable. Do not infer a healthy device from an absent row.
findmnt --target '/var/lib' -o TARGET,SOURCE,FSTYPE
lsblk -o NAME,KNAME,MAJ:MIN,TYPE,MOUNTPOINTS
head -n 12 /proc/diskstatspidstat reports little or no I/O
Processes may have exited, visibility may be restricted, accounting may be unavailable, or buffered/remote I/O may not match the device interval. Verify a candidate PID immediately; PIDs are reused. comm avoids dumping private arguments.
ps -p '1234' -o pid=,ppid=,user=,comm=,lstart=
cat '/proc/1234/cgroup'The service cgroup vanished or changed
Units can stop or move as processes restart. Rediscover ControlGroup and the cgroup2 mount; update the public example only after confirming scope. Never create a directory under cgroupfs to make the read succeed.
systemctl show 'example.service' -p LoadState -p ActiveState -p MainPID -p ControlGroup
findmnt -t cgroup2 -o TARGET,FSTYPE