vmstat (virtual memory statistics) prints one compact line per interval covering processes, memory, swap, disk I/O and CPU. When a server is slow, it’s often the fastest way to tell what kind of problem it is: CPU, memory pressure, or disk.
Run it with an interval
vmstat 1 10 # every second, 10 times
vmstat -w 1 # wide output, easier to read
vmstat -S M 1 # memory in MB
Ignore the first line. It shows averages since boot. The following lines show the current state.
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
3 0 0 412000 81000 2210000 0 0 5 40 900 1500 35 5 59 1 0
9 4 512000 35000 12000 180000 420 910 6800 2100 4100 8800 20 10 5 60 5
The first data line is a healthy server. The second is in trouble.
The columns
procs
- r — runnable processes, either running or waiting for a CPU. Consistently above the number of cores (
nproc) means CPU saturation. - b — processes blocked in uninterruptible sleep, usually waiting on disk I/O. Anything consistently above 0 deserves a look.
memory (KiB by default)
- swpd — swap in use.
- free — unused RAM. Low is normal, because Linux uses spare RAM as cache.
- buff / cache — buffers and page cache, which can be reclaimed when apps need memory.
Don’t judge memory by free alone. See free command.
swap
- si — swapped in from disk per second.
- so — swapped out to disk per second.
These matter more than swpd. Some swap usage with si/so at 0 is harmless: idle pages were moved out once. Continuous non-zero si and so means the server is short of RAM and is thrashing. Everything gets slow.
io
- bi — blocks read from disk per second.
- bo — blocks written per second.
system
- in — interrupts per second.
- cs — context switches per second. Very high values with high
sycan point to too many threads or processes competing.
cpu (% of total CPU time)
- us — user code (your apps).
- sy — kernel.
- id — idle.
- wa — waiting for I/O.
- st — steal, time the hypervisor gave to other VMs. Relevant on a VPS.
Reading patterns
| Pattern | Diagnosis |
|---|---|
r > cores, us high, id ≈ 0 |
CPU-bound. Find the process with top, then optimise or scale |
b > 0, wa high, bi/bo high, si/so = 0 |
Disk-bound. Check iostat, slow queries, backups |
si/so > 0 continuously, free low, wa high |
Out of memory and swapping. Reduce memory use or add RAM |
sy high, cs very high |
Too many workers or threads, or kernel contention |
st consistently > 5–10% |
Host CPU contention. Contact the provider or consider a dedicated server |
| Everything low but the site is slow | Look elsewhere: the network, an external API, the database on another host, app locks |
The second line in the example above shows memory exhaustion: si/so of hundreds of KB/s, little free memory, a tiny cache, and 60% wa, with 4 processes blocked. Fix the memory problem and the I/O wait disappears. That might mean lowering PHP-FPM max_children or the MySQL buffer pool, or upgrading the plan. See PHP-FPM tuning and MySQL buffer pool.
Other vmstat modes
vmstat -s # memory and event counters since boot
vmstat -d # per-disk statistics
vmstat -t 1 # add a timestamp to each line (good for logging)
vmstat -a 1 # active/inactive memory instead of buff/cache
Log during an incident window for later analysis:
vmstat -tw 5 720 > /tmp/vmstat-$(date +%F).log # one hour at 5 s intervals
vmstat in the toolbox
| Question | Tool |
|---|---|
| What kind of bottleneck? | vmstat |
| Which process? | top, htop, ps |
| Which disk, how busy, what latency? | iostat |
| Which process is doing the I/O? | iotop, pidstat -d 1 |
| History over days | sar (sysstat) or a monitoring tool |
vmstat comes with the procps package, which is installed everywhere.
Quick reference
| Column | Watch for |
|---|---|
r |
> CPU cores, sustained |
b |
> 0, sustained |
si / so |
Any continuous activity |
wa |
> 10–20% |
st |
> 5–10% on a VPS |
id |
Near 0 with high r |
Related: load average and top.