How to Diagnose CPU Bottlenecks and Memory Pressure in Linux
A beginner-friendly, production-safe guide to finding out whether a slow Linux server is struggling with CPU, memory, storage, or a runaway process.
Learn what the important Linux performance numbers mean, which commands to run first, and how to respond safely without making the incident worse.
Handling a critical ticket while a production server is grinding to a halt is stressful. The fastest engineers are not the ones who type the most commands. They are the ones who preserve evidence, separate CPU pressure from memory and I/O pressure, and choose the lowest-risk action that restores service.
A high load average is not a complete diagnosis. Compare CPU, available memory, swap activity, I/O wait, processes, and logs before changing the system.
Start with the simple picture
A slow Linux server usually needs you to answer three questions:
- Is the CPU too busy? Think of the CPU as workers at a service counter. If every worker is busy and more work keeps arriving, a queue forms.
- Is the server running short of memory? Think of RAM as a fast work desk. When the desk is full, Linux may move less-used information to much slower disk space called swap.
- Are programs waiting for storage or another I/O operation? The CPU may not be busy at all; applications can still feel frozen while they wait for a slow disk, network storage, or heavy swapping.
Your goal is not to react to one large number. Your goal is to identify which of these three situations is delaying useful work.
Beginner glossary: the numbers you will see
| Term | Meaning in plain language |
|---|---|
| Load average | How much work is running or waiting. The three values show averages for the last 1, 5, and 15 minutes. |
us | User CPU time: applications such as Java, Node.js, Python, Nginx, or a database are using the CPU. |
sy | System CPU time: the Linux kernel is busy doing work such as networking, storage operations, interrupts, or many system calls. |
id | Idle CPU time. A value close to zero means little CPU capacity is currently available. |
wa | I/O wait: programs are waiting for storage or another I/O operation. High wa is not the same as high application CPU use. |
available | Memory Linux can realistically provide to applications without heavy swapping. This is more useful than the free column. |
si/so | Swap in and swap out. Repeated values above zero can mean Linux is actively moving memory pages between RAM and disk. |
| PID | Process ID: the unique number Linux assigns to a running process. |
| OOM | Out Of Memory. Linux may kill a process when it cannot safely provide more memory. |
Record the timestamp, alert, affected service, current load, memory state, top processes, and recent kernel messages. A restart may restore service, but without evidence it can erase the path to the root cause.
The 60-second initial triage
Start with four commands. Run them one at a time and read the explanation below before trying more advanced tools.
uptime
free -h
top
vmstat 1 5
uptimeshows the load average. Runnprocto see how many logical CPUs the server has.free -hshows memory and swap in human-readable units. Focus first on theavailablememory.topshows CPU fields and which processes are using the most CPU or memory. PressPto sort by CPU orMto sort by memory.vmstat 1 5takes five samples, one second apart. Ignore the first line because it summarizes activity since boot; use the later lines to see what is happening now.
Compare load average with the CPU count, but treat it as a clue. A load above the CPU count suggests a queue is building. The queue may be waiting for CPU time or may be blocked on I/O, so check us, sy, id, and wa before deciding.
| Signal | Likely direction | Confirm with |
|---|---|---|
High load, id near zero, high us | An application is keeping the CPU busy | Find the top CPU process with top or ps |
High load and high sy | The Linux kernel is doing a lot of work | Check system calls, context switches, networking, and storage activity |
High load and high wa | Programs are waiting for storage or I/O | Check disk latency with iostat -xz and activity with pidstat -d |
Low available memory with repeated si/so | Linux is actively moving data between RAM and swap | Watch several vmstat samples and identify growing processes |
| A service disappeared and the kernel logged a killed process | Linux probably used the OOM killer | Check journalctl -k and record the killed process |
Part 1: is the CPU the bottleneck?
A CPU bottleneck exists when runnable work consistently demands more compute time than the available CPUs can supply. A brief spike is not enough; look for sustained pressure that matches the user-visible slowdown.
1. Read the CPU fields correctly
vmstat 1 5
mpstat -P ALL 1 5
pidstat -u -w 1 5
us(user): application code is consuming CPU. Compression, encryption, query processing, garbage collection, loops, or expensive requests may be involved.sy(system): the kernel is doing substantial work. Investigate syscalls, networking, interrupts, I/O, and context switching.id(idle): close to zero across the observation window means little CPU capacity remains.wa(I/O wait): the CPU is idle while tasks wait for I/O. This points away from pure compute saturation and toward storage or another blocking path.rinvmstat: runnable processes. A sustained run queue above available CPUs supports a CPU contention diagnosis.
2. Isolate the process and thread
ps -eo pid,ppid,stat,comm,%cpu,%mem --sort=-%cpu | head -n 11
top -H -p <PID>
pidstat -u -w -p <PID> 1 5
For a multithreaded process such as Java, Node.js, Python workers, Nginx, or a database, the process total is only the first clue. Use the thread view to identify whether one thread is spinning, many workers are legitimately busy, or the process is spending time in context switches.
3. Check pressure, not just utilization
cat /proc/pressure/cpu
cat /proc/pressure/io
This is an optional advanced check. Pressure Stall Information (PSI) measures how much time programs lose while waiting for CPU, memory, or I/O resources. Rising CPU some averages mean at least some tasks are waiting for CPU time. Beginners can first become comfortable with top, free, and vmstat, then add PSI later.
4. Mitigate with the lowest-risk action
- Reduce incoming work: pause a batch, shed optional traffic, lower worker concurrency, or scale out if the platform supports it.
- Lower a non-critical process priority:
sudo renice -n 19 -p <PID>. Verify the new priority and service impact. - Constrain a known-safe workload: prefer service, container, or cgroup CPU limits. Temporary affinity such as
sudo taskset -cp 0,1 <PID>can help in a controlled incident, but poor affinity choices can make latency worse. - Stop gracefully: use the service manager or
kill -TERM <PID>, wait, and confirm shutdown. Usekill -KILL <PID>only as a last resort because it prevents cleanup and can leave partial work behind.
Part 2: is memory pressure slowing the server?
Linux intentionally uses spare RAM for page cache, so the free column is not the number that matters most. Focus on available, active reclaim, swap-in and swap-out activity, pressure, process growth, and OOM events.
1. Confirm active pressure
free -h
vmstat 1 10
cat /proc/pressure/memory
pidstat -r 1 5
Allocated swap is not automatically a problem; Linux may leave cold pages in swap even after pressure has passed. Sustained non-zero si and so in vmstat, low available memory, elevated memory PSI, and slow I/O together are much stronger evidence of active thrashing.
2. Find the consumers and the growth pattern
ps -eo pid,ppid,stat,comm,rss,%mem --sort=-rss | head -n 11
pidstat -r -p <PID> 1 10
cat /proc/<PID>/status | egrep 'VmRSS|VmSwap|Threads'
One snapshot tells you who is large. Repeated samples tell you who is growing. Distinguish expected cache, a workload spike, too many workers, a process leak, and a restrictive container memory limit before deciding the fix.
3. Check for OOM killer intervention
journalctl -k -g 'oom|out of memory|killed process'
dmesg -T | grep -i -E 'oom|out of memory|killed process'
Record the killed PID, process name, cgroup or container, memory totals, and timestamp. If the host has free memory but a container is killed, inspect the workload's cgroup limit rather than assuming the entire server ran out of RAM.
4. Mitigate memory pressure safely
If you are a fresher or do not own the production service, collect the evidence and involve the service owner before changing limits, stopping processes, or adjusting OOM settings.
- Stop the growth: pause the leaking or non-critical workload, reduce concurrency, reject optional work, or scale capacity.
- Restart only with evidence: if an approved restart is the recovery action, capture diagnostics first and watch memory after recovery so a leak does not silently return.
- Protect critical services carefully: a temporary adjustment is
echo -500 | sudo tee /proc/<PID>/oom_score_adj. For systemd services, use a reviewedOOMScoreAdjust=setting. Avoid blanket-1000protection: making one process unkillable can force the kernel to kill another essential service. - Fix the capacity or limit: tune heap and worker counts, correct cgroup limits, add memory, or repair the leak after service is stable.
echo 3 > /proc/sys/vm/drop_caches does not repair a memory leak and can create an I/O spike while useful cache is rebuilt. Reserve cache dropping for an approved diagnostic experiment with a clear hypothesis, not as a standard production response.
A production incident sequence you can reuse
- Declare impact: what is slow or unavailable, when it started, and which users or services are affected?
- Capture a baseline: timestamp, CPU count, load, CPU fields, available memory, swap activity, PSI, top processes, and kernel events.
- Classify the pressure: CPU queue, I/O wait, active memory reclaim, OOM, or a mixture.
- Identify the owner: process, thread, service, container, dependency, recent deployment, or workload change.
- Mitigate reversibly: shed work, lower priority, scale, or stop gracefully before considering forceful actions.
- Validate: repeat the same measurements and confirm both system signals and user experience improved.
- Preserve follow-up evidence: commands, timestamps, graphs, process IDs, logs, action taken, result, rollback path, and prevention item.
Observe the symptom and metrics. Confirm the likely bottleneck with more than one signal. Act using the least risky approved change. Verify by repeating the same commands and checking the user experience.
Quick reference for the incident channel
| Goal | Command | Watch for |
|---|---|---|
| System overview | uptime; nproc; top | Load trend, run queue, CPU fields, dominant process |
| CPU by core | mpstat -P ALL 1 5 | One hot core versus host-wide saturation |
| Memory and I/O stream | vmstat 1 10 | r, si/so, wa, CPU state |
| Pressure view | cat /proc/pressure/{cpu,memory,io} | Short- and medium-window stall time |
| Process trend | pidstat -u -r -d -p <PID> 1 | CPU, faults, RSS growth, reads, and writes |
| OOM audit | journalctl -k -g 'oom|killed process' | Killed process, cgroup, timestamp, allocation failure |
The key lesson
Do not optimize the loudest metric. Diagnose the resource that is making useful work wait. CPU utilization, load average, free memory, swap, and I/O wait become meaningful only when they agree with process trends, pressure data, logs, and the user-visible symptom. That evidence-first habit is what makes a Linux response fast, safe, and credible.
Recommended resources
Manual references stay pinned first, and AI adds extra official or trusted links matched to the lesson topic.
Related reading
These pages connect closely to the current lesson and help learners keep moving through the same subject cluster.
- Linux Performance and Production Checks
Move from command familiarity into production-minded checks for CPU, memory, disk, uptime, and dependency health.
- Linux Logs, Services, and Process Diagnosis
Learn how to inspect service state, logs, and processes so Linux incidents stop feeling random.
- Linux Networking Checks for Support Engineers
Learn simple Linux network checks for DNS, IP, ports, routes, and connectivity issues that support engineers see often.
- Linux for Support and Operations
Learn Linux the practical way: commands, services, logs, permissions, and production-minded checks for support and engineering work.