Calculate per-core CPU utilization from mpstat metrics across a multi-core system.
Aggregate CPU utilization (as reported by `top`'s single %Cpu(s) line) can mask serious per-core imbalance — a system averaging 50% busy could be one core pegged at 100% while three sit idle, which behaves very differently for latency-sensitive single-threaded work than four cores evenly at 50%. Computing per-core utilization from busy/total tick ratios (as `mpstat -P ALL` reports) and comparing the spread between the busiest and idlest core reveals imbalance caused by IRQ concentration, poor thread/process CPU affinity, or single-threaded bottlenecks pinning one core while others go unused.
Per-core utilization and imbalance
core_util% = busy_ticks / total_ticks × 100; imbalance = max(core_util%) − min(core_util%)
Common causes include a single-threaded application or bottleneck (which can only ever use one core at a time), interrupt handling concentrated on one core (check /proc/interrupts per-CPU columns), or CPU affinity pinning that inadvertently confines work to a subset of cores rather than letting the scheduler balance load.
`mpstat -P ALL 1` prints per-core %usr/%sys/%iowait/%idle breakdowns every second, and `htop` (with per-core meters enabled in its display settings) gives a live visual bar per core — both make imbalance immediately visible without manual tick-counter math.
Yes — CFS actively load-balances runnable tasks across cores (and across NUMA nodes, with awareness of topology), but it can't split a single thread across multiple cores, so genuinely single-threaded bottlenecks or explicit CPU affinity pinning can still produce lasting imbalance despite the scheduler's efforts.