“The server is slow” is a symptom, not a diagnosis. Triage means finding which resource is saturated in a few minutes, before touching anything. This post gives a fixed order of checks and explains how to read each number.
Versions in use on this date. sysstat 11.6.1 (iostat, mpstat, pidstat, sar) and procps-ng 3.3.12 on Ubuntu 18.04.3 LTS. Install sysstat with sudo apt install sysstat, then set ENABLED="true" in /etc/default/sysstat so sar keeps history.
The method
flowchart TB
S[Slow server reported] --> U[uptime<br/>load averages]
U --> V[vmstat 1<br/>run queue swap io wait]
V --> C{What dominates?}
C -->|high us or sy| CPU[CPU - mpstat and pidstat -u<br/>find hot process]
C -->|high wa or D state| IO[Disk - iostat -x<br/>find busy device and process]
C -->|si so non zero or low avail| MEM[Memory - free and ps by RSS<br/>OOM kills in dmesg]
C -->|all quiet| NET[Network and app<br/>ss and application logs]
CPU --> FIX[Decide - tune, scale or fix code]
IO --> FIX
MEM --> FIX
NET --> FIX
Use the USE method: for each resource ask about Utilisation, Saturation and Errors.
1. Load average
uptime
nproc
Load is the average number of tasks running or waiting (including waiting for disk) over 1, 5 and 15 minutes. Compare to the core count: load 8 on 8 cores is full; load 8 on 2 cores means a queue. A rising 1-minute value versus the 15-minute shows whether it is getting worse.
2. vmstat
vmstat 1 5
| Column | Reading |
|---|---|
r |
Runnable tasks; sustained above core count means CPU saturation |
b |
Tasks blocked on I/O |
si / so |
Swap in and out; any steady non-zero value means memory pressure |
wa |
CPU time waiting for I/O |
us / sy / id / st |
User, kernel, idle, steal from hypervisor |
3. CPU
mpstat -P ALL 1 3 # per-core usage; one core at 100% = single-threaded bottleneck
pidstat -u 1 5 # CPU per process over time
top -o %CPU # (or: top, then P)
High sy points to the kernel (many system calls, network handling, context switches); high st on a VM means the host is oversubscribed, which only the provider can fix.
4. Memory
free -m
ps -eo pid,user,rss,cmd --sort=-rss | head
vmstat -s | head -12
dmesg -T | grep -i -E 'out of memory|killed process'
Read available, not free: Linux fills spare RAM with cache that is released on demand. Concern starts when available is low and swap is in use or the OOM killer fired.
5. Disk
iostat -xz 1 3
pidstat -d 1 5 # per-process read and write rates
df -h; df -i
sudo lsof +L1 | head
| iostat column | Reading |
|---|---|
%util |
Near 100% means the device is saturated (misleading on SSD/NVMe, check latency too) |
await |
Average ms per request; milliseconds on SSD, tens of ms on spinning disk is normal, hundreds is not |
aqu-sz |
Queue depth |
r/s, w/s, rkB/s |
Throughput |
Cloud disks have IOPS and throughput limits; a burst-credit volume that runs out of credits looks exactly like a sudden disk bottleneck.
6. Network and application
sar -n DEV 1 3 # interface throughput
ss -s # socket summary, look for huge TIME-WAIT counts
ss -tn state established | wc -l
sudo tail -n 100 /var/log/syslog
If the host looks idle yet the application is slow, the problem is probably inside it: slow database queries, lock waits, an external API, DNS delays or thread pool limits. Check application logs and timings next.
Look back in time with sar
sar -u -s 09:00:00 -e 11:00:00 # CPU history
sar -r # memory history
sar -q # load and run queue history
sar -d -p # disk history
History answers “what happened at 3 AM” when nobody was watching.
Write it down
Record what you saw (numbers, timestamps) and the single change you made, one at a time. Add the bottleneck to your monitoring as an alert, so next time you hear about it before the user does.