Chris Siebenmann looks back at how the Unix load average, simple in the single-CPU 3BSD era, ran into three design questions as machines gained multiple processors and threads.

The first question: on a four-CPU machine with two busy processes, is the load average 2 or 0.5? Modern Unixes count runnable processes globally, so the answer is 2 regardless of CPU count. Irix initially normalized by capacity instead, so the number meant roughly the same degree of loadedness on any machine. That choice lost, and today you need the CPU count alongside the load average to judge whether a system is overloaded.

The second question is thread counting. Kernels cannot see green threads or user-level threads multiplexed onto fewer kernel objects, so early implementations counted only what the kernel knew about, sometimes only processes, not threads. Linux made threads a form of process, so they are fully visible. The issue persists in runtimes like Go: the load average shows active OS threads, not the number of goroutines waiting to run.

The third question is what gets counted beyond runnable processes. The original 3BSD load average included processes waiting on disk IO, and commercial Unixes such as Sun's copied that, with NFS IO counting as disk IO. Brendan Gregg's 2017 investigation showed Linux initially excluded IO waits but added them very early on. The BSDs have varied on this point.