Slow servers rarely announce the cause. A pegged CPU, a swapping kernel, and a saturated disk all look the same from the outside: lag. Five tools, all built on the /proc pseudo-filesystem, separate these causes in under a minute. This guide shows how to install each one, read its output, and combine them into a repeatable triage routine.
Quick Takeaways
- top ships everywhere and gives instant per-process CPU and memory data.
- htop and btop add interactive sorting, process trees, and graphs for live diagnosis.
- vmstat exposes system-wide memory pressure, swapping, and run-queue length.
- iostat reveals disk saturation through
%util,await, and queue depth.
| Tool | Best For | Interface | Installed by Default | Overhead |
|---|---|---|---|---|
top |
Quick process triage | Interactive TUI | Yes | Low |
htop |
Process management | Interactive TUI | No | Low |
btop |
Full-system dashboards | Graphical TUI | No | Medium |
vmstat |
Memory, swap, CPU, run queue | Scrolling text | Yes | Minimal |
iostat |
Disk throughput and latency | Scrolling text | No (sysstat) |
Minimal |
Prerequisites
You need a shell with sudo access for installation. Reading metrics requires no privileges, but killing or renicing other users’ processes does.
Install the missing tools:
# Debian / Ubuntu
sudo apt update && sudo apt install -y htop btop sysstat
# RHEL / Rocky / AlmaLinux (htop and btop live in EPEL)
sudo dnf install -y epel-release
sudo dnf install -y htop btop sysstat
# Arch
sudo pacman -S htop btop sysstat
Verify the installs:
htop --version && btop --version && iostat -V
How Linux Exposes Performance Data
Every tool here parses files under /proc and /sys. Key sources:
| File | Contents |
|---|---|
| /proc/loadavg | 1, 5, and 15-minute load averages |
| /proc/meminfo | Memory, cache, swap counters |
| /proc/stat | Cumulative CPU time per state |
| /proc/diskstats | Per-device I/O counters |
| /proc/[pid]/status | Per-process memory and state |
The kernel only keeps cumulative counters. Tools calculate rates by sampling twice and subtracting. That is why the first line of vmstat and iostat shows averages since boot, and later lines show the interval.
Monitoring with top
top is the baseline tool. Start it:
top
Reading the Header
top - 14:02:11 up 12 days, load average: 3.12, 2.87, 2.40
Tasks: 214 total, 2 running, 211 sleeping, 0 stopped, 1 zombie
%Cpu(s): 41.2 us, 8.1 sy, 0.0 ni, 47.3 id, 3.0 wa, 0.0 hi, 0.4 si, 0.0 st
MiB Mem : 15890.2 total, 612.4 free, 9120.8 used, 6157.0 buff/cache
MiB Swap: 2048.0 total, 1900.1 free, 147.9 used. 6330.5 avail Mem
Load average counts processes running or waiting for CPU (plus uninterruptible I/O waiters on Linux). Compare it to your core count. Check cores with nproc. On an 8-core machine, a load of 8.0 means full utilization.
The CPU line breaks down as:
| Field | Meaning | Red Flag |
|---|---|---|
us |
User-space code | Sustained >90% |
sy |
Kernel code | >30% suggests syscall or driver load |
ni |
Niced processes | Informational |
id |
Idle | Near 0% means saturation |
wa |
Waiting on I/O | >10% points to disk or NFS |
hi / si |
Hardware / software interrupts | High si suggests network load |
st |
Stolen by hypervisor | >5% means noisy neighbors |
Use avail Mem, not free. Linux fills spare RAM with page cache and reclaims it on demand. A low free value is normal.
Essential Interactive Keys
| Key | Action |
|---|---|
P |
Sort by CPU |
M |
Sort by memory |
1 |
Show per-core CPU |
c |
Show full command lines |
k |
Kill a process by PID |
r |
Renice a process |
H |
Toggle thread view |
W |
Save current settings to ~/.config/procps/toprc |
Batch Mode for Logging
top -b -n 1 -o %MEM | head -n 20 > /tmp/top-snapshot.txt
-bruns in batch mode (no TUI).-n 1takes one iteration.-o %MEMsorts by memory.
Monitoring with htop
htop improves on top with color-coded meters, mouse support, horizontal scrolling, and a tree view.
htop
Useful Keys
| Key | Action |
|---|---|
F5 |
Tree view of parent/child processes |
F6 |
Choose sort column |
F4 |
Filter by string |
F9 |
Send a signal |
F2 |
Setup (add columns like IO_RATE) |
Space |
Tag a process for bulk actions |
u |
Filter by user |
Reading the Memory Bar
The memory bar uses colors: green for used, blue for buffers, yellow for cache. A mostly yellow bar is healthy. A full green bar with active swap is not.
Start htop Filtered
htop -u www-data
-u limits the view to one user. Add -p 1234,5678 to watch specific PIDs.
Monitoring with btop
btop combines CPU, memory, disk, network, and process panels in one screen with history graphs.
btop
| Key | Action |
|---|---|
m |
Cycle display modes |
f |
Filter processes |
e |
Process tree |
+ / - |
Adjust update interval |
Esc |
Open menu and options |
q |
Quit |
Change the refresh rate and theme in ~/.config/btop/btop.conf:
update_ms = 1000
color_theme = "Default"
proc_sorting = "cpu lazy"
Use btop when you need to correlate events. A CPU spike that lines up with a network burst and a disk write tells a story that separate tools would not.
top vs. htop vs. btop
| Criteria | top | htop | btop |
|---|---|---|---|
| Resource Consumption | Lowest | Low | Moderate |
| Disk and Network Panels | No | No | Yes |
| Process Tree | Limited (V) |
Yes (F5) |
Yes (e) |
| Availability on Minimal Servers | Always | Package install | Package install |
| Scripting Support | Batch mode | Limited | None |
| Best Use | Recovery shells | Daily admin | Live dashboards |
Monitoring with vmstat
vmstat reports virtual memory, processes, I/O, and CPU in one compact table. It is ideal for SSH sessions and scripts.
vmstat 2 5
2is the interval in seconds.5is the number of samples.
Sample Output
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
4 1 151552 626100 210420 5920000 0 0 120 340 1500 3200 42 8 47 3 0
Column Reference
| Column | Meaning | What to Watch |
|---|---|---|
r |
Runnable processes | Consistently > core count = CPU saturation |
b |
Blocked (uninterruptible sleep) | Non-zero often = I/O stall |
swpd |
Swap used (KB) | Growth over time |
si / so |
Swap in/out (KB/s) | Sustained non-zero = memory pressure |
bi / bo |
Blocks in/out | Disk activity volume |
in |
Interrupts per second | Sudden jumps indicate hardware or network storms |
cs |
Context switches per second | Very high values suggest thread contention |
Swap activity matters more than swap usage. A static swpd with si/so at zero is harmless. Active si/so means the kernel is thrashing.
Useful Variants
vmstat -s # Memory and event counter summary
vmstat -d # Per-disk statistics
vmstat -S M 2 # Display in megabytes
vmstat -a 2 # Show active/inactive memory
Monitoring with iostat
iostat ships in the sysstat package. It is the primary tool for disk analysis.
iostat -xz 2
-xshows extended statistics.-zhides devices with zero activity.2sets a 2-second interval.
Discard the first report, since it is the average since boot.
Key Extended Fields
| Field | Meaning | Warning Sign |
|---|---|---|
r/s, w/s |
Reads/writes per second | Compare with device IOPS limits |
rkB/s, wkB/s |
Throughput | Near device bandwidth limit |
r_await, w_await |
Average latency in ms | >20 ms on SSD, >100 ms on HDD |
aqu-sz |
Average queue depth | Persistently >1 on HDD |
%util |
Time the device was busy | ~100% on a single-queue device = saturated |
%util can mislead on NVMe and RAID arrays. These devices handle parallel requests, so 100% busy does not always mean maxed out. Judge by await and aqu-sz.
CPU and Per-Device Views
iostat -c 2 # CPU report only
iostat -dx sda 2 # One specific device
iostat -h -xz 2 # Human-readable units
Compare Storage Behavior
| Storage Type | Typical Latency | Queue Behavior | Watch Metric |
|---|---|---|---|
| HDD (7.2k RPM) | 5–15 ms | Saturates quickly | %util, await |
| SATA SSD | 0.1–1 ms | Moderate parallelism | await, aqu-sz |
| NVMe SSD | <0.1 ms | High parallelism | await, IOPS |
| Network (NFS/iSCSI) | Variable | Depends on network | await, wa in top |
A Repeatable Triage Workflow
Run the tools in this order to isolate the bottleneck fast.
- Check load and cores:
uptimeandnproc. - Scan system-wide state:
vmstat 1 5. Look atr,b,si,so,wa. - Find the offender:
toporhtop. Sort by CPU (P) or memory (M). - Confirm disk suspicion:
iostat -xz 1 5. Checkawaitand%util. - Correlate over time: open
btopand watch graphs.
Decision Matrix
| Symptom | Likely Cause | Confirm With |
|---|---|---|
High us, high r |
CPU-bound application | top, htop |
High wa, high b |
Disk or network storage stall | iostat -xz |
Non-zero si/so |
Memory exhaustion | vmstat, free -h |
High sy, high cs |
Lock contention or syscall storm | pidstat -w, strace |
High st |
Overcommitted hypervisor | Cloud provider metrics |
| High load, low CPU use | Processes in D state (I/O) |
top state column |
Real-World Scenarios
Scenario 1: Server Slow, CPU Looks Idle
Load average is 14 on a 4-core box, but us is 5%. This pattern points to I/O wait.
vmstat 1 5
iostat -xz 1 5
If wa is high and w_await is above 200 ms, a disk is overloaded. Find the culprit:
sudo iotop -oPa
Alternatively, install pidstat from sysstat and run pidstat -d 1.
Scenario 2: Memory Leak Suspected
Watch the process directly:
watch -n 5 'ps -eo pid,comm,rss,vsz --sort=-rss | head -n 10'
Growing RSS for one process over hours confirms a leak. Check whether the OOM killer has acted:
sudo dmesg -T | grep -i -E "out of memory|oom-killer"
journalctl -k | grep -i oom
Scenario 3: Automating Metric Collection
Log vmstat and iostat with timestamps for later analysis. Create /usr/local/bin/perf-log.sh:
#!/usr/bin/env bash
LOG_DIR=/var/log/perf
mkdir -p "$LOG_DIR"
{
date -Is
vmstat 1 10
iostat -xz 1 10
top -b -n 1 -o %CPU | head -n 15
echo "-----"
} >> "$LOG_DIR/perf-$(date +%F).log"
Make it executable and schedule it:
sudo chmod +x /usr/local/bin/perf-log.sh
echo '*/5 * * * * root /usr/local/bin/perf-log.sh' | sudo tee /etc/cron.d/perf-log
Prevent disk saturation from the logs themselves. Create /etc/logrotate.d/perf:
/var/log/perf/*.log {
daily
rotate 14
compress
missingok
notifempty
}
Scenario 4: Enable Persistent History with sysstat
sysstat can record metrics continuously and let you query past events with sar. On Debian/Ubuntu, enable collection in /etc/default/sysstat:
sudo sed -i 's/ENABLED="false"/ENABLED="true"/' /etc/default/sysstat
sudo systemctl enable --now sysstat
Query yesterday’s CPU data:
sar -u -f /var/log/sysstat/sa$(date -d yesterday +%d)
On RHEL-based systems, the path is /var/log/sa/.
Common Pitfalls
- Reading the first iostat/vmstat line as current data. It is the since-boot average.
- Treating
freememory as a problem. Useavailable. - Ignoring
st. On VMs, stolen time explains slowness that nothing inside the guest can fix. - Trusting
%utilalone on NVMe. Check latency. - Comparing load average to nothing. Always divide by core count.
- Sampling too briefly. Spikes can hide in 1-second windows. Collect at least 30 seconds.
Verification Checklist
After applying a fix, confirm improvement with the same commands you used to diagnose:
uptime
vmstat 1 10
iostat -xz 1 10
Compare r, wa, si/so, and await against your baseline. Save a baseline during healthy periods so you have something to compare against during incidents.
FAQ
What is the difference between top and htop?
top is preinstalled on virtually all Linux systems and offers lightweight, keyboard-driven monitoring. htop adds color meters, mouse support, a process tree, and easier sorting and filtering, but usually requires installation.
How do I check disk I/O performance in Linux?
Run iostat -xz 2 and discard the first report. Watch r_await and w_await for latency, aqu-sz for queue depth, and %util for how busy the device is. Use iotop or pidstat -d to find the responsible process.
What does a high load average mean on Linux?
Load average counts processes that are running, waiting for CPU, or blocked in uninterruptible I/O. Compare it with your core count from nproc. A load persistently above the core count means demand exceeds capacity, either CPU or I/O.
How do I know if my Linux server is swapping?
Run vmstat 1 5 and check the si and so columns. Sustained non-zero values mean the kernel is actively moving pages to and from swap. A non-zero swpd alone is not a problem.




