Where to start First steps track · 15 stages
Linux Labs

Load average: how many tasks wait for the CPU and the disk

12 min Ubuntu 24.04 · Linux 6.8 · procps 4.0

The average number of tasks running or waiting for a CPU (R) or for the kernel (D) over 1, 5 and 15 minutes.

Cheat sheet

8 commands Printable version
  • uptime load over 1, 5 and 15 minutes
  • nproc CPU count to compare with
  • cat /proc/loadavg same numbers + tasks in R / total
  • top load and the %Cpu(s) line
  • vmstat 1 5 r — wait for CPU, b — wait for disk
  • ps -eo stat,pid,pcpu,comm --sort=-pcpu | head CPU eaters
  • ps -eo stat,pid,wchan:30,cmd | awk '$1 ~ /^D/' who is in D
  • cat /proc/pressure/cpu share of time waiting for CPU

Overview

Load average is the average number of tasks that want to run: running or waiting for a free CPU (state R) and waiting for the kernel to finish an operation for them (state D). uptime, top and w print three numbers — the average over 1, 5 and 15 minutes:

text
student@ubuntu:~$ uptime
 23:38:05 up 3 min,  2 users,  load average: 2.90, 1.43, 0.57
student@ubuntu:~$ nproc
1

Load is counted in tasks; it has no percent. Compare it with the number of CPUs from nproc. On one CPU, 1.00 means "busy all the time, nobody queued", while 2.90 means that almost three tasks wanted to run at once on average. On eight CPUs the same 2.90 is an idle machine.

Three numbers

They are moving averages: the 1-minute one reacts to changes quickly, the 15-minute one smooths them out. The three together show the direction: 2.90, 1.43, 0.57 — the load grew in the last minutes, 0.30, 1.50, 2.80 — it is falling.

The number catches up with a new level gradually. Two tasks that keep the CPU busy for exactly one minute raise the 1-minute number to about 1.3; it reaches 2 after several minutes. A short spike barely shows in the 15-minute number.

What counts: R and D

Every 5 seconds the kernel recounts tasks in two states. A task is each thread: a program with eight busy threads adds 8.

State What the task is doing In load
R running or queued for a CPU yes
D uninterruptible sleep: waiting for a kernel operation — disk, filesystem, NFS yes
S sleeping until an event: input, a packet, a timer no
T, Z, I stopped, zombie, idle kernel thread no

The state shows in the STAT column of ps and the S column of top (see processes).

State D

A process in uninterruptible sleep waits for the kernel to finish an operation for it: a disk read, a write to a filesystem, a reply from an NFS server. It gets signals only when the wait is over — even kill -9:

text
student@ubuntu:~$ ps -eo stat,pid,wchan:30,cmd | awk '$1 ~ /^D/'
D       2147 percpu_rwsem_wait              touch /mnt/frz/f1
D       2148 percpu_rwsem_wait              touch /mnt/frz/f2
D       2149 percpu_rwsem_wait              touch /mnt/frz/f3
student@ubuntu:~$ kill -9 2147; sleep 1; ps -o stat,pid,cmd -p 2147
STAT     PID CMD
D       2147 touch /mnt/frz/f1

Here the filesystem was frozen with fsfreeze -f, and every write to it waits for the thaw. The WCHAN column is the kernel function the process sleeps in. Such tasks use no CPU, yet each one adds one to the load. Once the filesystem was thawed (fsfreeze -u), process 2147 exited at once: the pending SIGKILL took effect.

Load and CPU usage

Load tells you how many tasks want to run. The %Cpu(s) line in top tells you what the CPU is busy with. Together they tell two problems apart on a one-CPU machine:

What you see Tasks %Cpu(s) What is happening
load climbing to 2 two in R, 48.8 % each 100.0 us, 0.0 id two tasks share one CPU
load 2.90 three in D 0.0 us, 90.9 id, 0.0 wa tasks wait, the CPU is free

The fields of %Cpu(s) are shares of CPU time over the last interval:

Field Meaning
us program code
sy the kernel on behalf of programs: system calls, I/O
ni programs with a lowered nice priority
id idle
wa idle while someone waits for the disk (iowait)
st steal: the VM needed the CPU, but the hypervisor gave it to other machines

A process priority is lowered with nice and renice (see the nice value); its share goes to ni.

wa counts only waiting for a device. In the example above the three D processes wait for the filesystem to thaw and never reach the disk, so wa is 0.0. When a process waits for the disk itself, wa grows: during a dd … oflag=direct write on the same machine, vmstat showed wa 82. Yet wa is still idle time: a task that needs the CPU takes that time, and wa drops towards zero while the disk stays just as busy.

Where the numbers come from

uptime, top and monitoring systems read /proc/loadavg:

text
student@ubuntu:~$ cat /proc/loadavg
1.72 0.68 0.25 1/125 2118

The first three fields are the load average. 1/125 is how many tasks are in R right now and how many tasks exist. The last field is the PID of the most recently created process.

Pressure: /proc/pressure

Load adds up waiting for the CPU and waiting for the kernel into one number. The files /proc/pressure/cpu, io and memory (PSI, pressure stall information) keep them apart. This is cpu while two stress-ng --cpu 2 tasks share one CPU:

text
student@ubuntu:~$ cat /proc/pressure/cpu
some avg10=64.78 avg60=18.21 avg300=4.14 total=12842145
full avg10=0.00 avg60=0.00 avg300=0.00 total=0

some avg10=64.78 means that during 64.78 % of the last 10 seconds at least one task waited for a CPU; avg60 and avg300 are the same over a minute and over 5 minutes. full in io and memory is the share of time when all active tasks waited at once. For cpu at the whole-machine level full is always 0.

Recipes

3

Load above the CPU count: who is queued

text
student@ubuntu:~$ ps -eo stat,pid,ni,pcpu,comm --sort=-pcpu | head -4
STAT     PID  NI %CPU COMMAND
R        975   0 48.8 stress-ng-cpu
R        976   0 48.8 stress-ng-cpu
Ss         1   0 10.8 systemd

Two R tasks at 48.8 % share one CPU. Next: wait, lower the priority (renice -n 10 -p 975, see processes) or stop the process (kill).

Find what D processes wait for

bash
ps -eo stat,pid,wchan:30,cmd | awk '$1 ~ /^D/'  # who is in D
grep State /proc/2147/status    # State: D (disk sleep)
sudo cat /proc/2147/stack       # kernel stack, root only
text
student@ubuntu:~$ sudo cat /proc/2147/stack
[<0>] percpu_rwsem_wait+0x103/0x120
[<0>] mnt_want_write+0x9c/0xd0
[<0>] open_last_lookups+0x319/0x400
…
[<0>] __x64_sys_openat+0x55/0xa0

Read the stack bottom up: the openat system call, a request to write to the mount point (mnt_want_write), the wait: the process waits for the filesystem. nfs_ or rpc_ functions in the stack mean it waits for an NFS server; network filesystems are listed by findmnt -t nfs,nfs4,cifs.

Watch the load over time

bash
vmstat 1 5                        # r and b every second
watch -n 5 cat /proc/loadavg      # load every 5 seconds

In vmstat, column r is tasks in R (running and waiting for a CPU), b is tasks waiting for the disk. All columns are in system-monitoring.

Troubleshooting

5

High load, but the CPU is idle

top shows 90.9 id, and the load on one CPU is 2.90. So tasks are in D. Find them (ps … | awk '$1 ~ /^D/', recipe above) and see what they wait for:

  • wa is high and b in vmstat grows — they wait for the disk: iostat -x and sudo pidstat -d 1 show which disk and which process (see pidstat-iostat);
  • wa 0, b 0 — they wait for something other than a device: a frozen filesystem, an NFS server, a lock in the kernel. The stack is in /proc/<pid>/stack.

A task stuck in D longer than kernel.hung_task_timeout_secs (120 seconds on Ubuntu) gets into the kernel log. Here the threshold was lowered to 20:

text
student@ubuntu:~$ sudo journalctl -k -o cat | grep 'blocked for'
INFO: task touch:2147 blocked for more than 20 seconds.

A D process ignores kill -9

The signal waits for the kernel operation to end. Remove the cause of the wait: bring back the disk or the NFS server, thaw the filesystem (sudo fsfreeze -u <mount point>). The process then receives the pending signal by itself. If the device is gone for good, the process stays in D until a reboot.

Is a load of 1.00 on one CPU a lot?

There is no queue: the CPU is busy all the time and nobody waits. Things slow down when the load stays above nproc for long and the r column in vmstat is larger than the CPU count. A short spike of the 1-minute number with a calm 15-minute one is normal work.

Inside a container the load is the whole machine's

There is one /proc/loadavg per kernel: uptime inside a container shows the load of the host with all its containers. Check the load of one container with docker stats (see docker).

High st on a virtual machine

st (steal) means the VM needed the CPU, but the hypervisor gave it to other machines. The load grows: tasks stay in the queue longer. This cannot be fixed inside the VM — the host needs a free CPU.

Terms

2
state D (uninterruptible sleep)
The process waits for the kernel to finish an operation for it: disk I/O, a filesystem write, a reply from an NFS server. Signals, even SIGKILL, take effect only after the wait ends. It counts towards load average. Also appears in: Processes, dmesg, System monitoring: where to start when the server is slow, kill and 6 more
iowait
CPU idle time while at least one process waits for the disk: wa in top and vmstat, %iowait in iostat and mpstat. It is a kind of idle time: when the CPU has other work, wa drops to zero although the disk is still busy. Also appears in: System monitoring: where to start when the server is slow

See also

  • uptime-who — uptime, w and who is logged in.
  • top — load, the %Cpu(s) line and processes in one window.
  • processes — states, signals and the nice priority.
  • system-monitoring — the order of checks for "the server is slow".
  • kill — signals that a D process will receive later.
  • docker — CPU and memory limits of a container.
  • stress-ng — CPU load for experiments with load.
Loading…