On modern multi-core Ubuntu servers running intensive network, database, or virtualisation workloads, managing how the Linux kernel handles Hardware Interrupt Requests (IRQs) is critical for system responsiveness. When high-speed network interfaces (e.g., 10 GbE or 40 GbE NICs), NVMe storage controllers, and GPU compute accelerators generate hundreds of thousands of interrupts per second, routing all interrupts to CPU core 0 causes CPU saturation, severe packet loss, and thread starvation.
To distribute interrupt processing evenly across available processor cores, Ubuntu employs the irqbalance daemon. While irqbalance works effectively in default desktop and general-purpose server deployments, high-performance computing, telecom NFV, and real-time audio environments often require dedicated CPU cores completely shielded from hardware interrupts. This guide demonstrates how to inspect, configure, and fine-tune irqbalance on Ubuntu Server.
Understanding irqbalance Architecture and CPU Affinity
The Linux kernel allows configuring the SMP interrupt affinity of any hardware device by writing a hexadecimal CPU bitmask to /proc/irq/[number]/smp_affinity. The irqbalance daemon monitors interrupt counts across /proc/interrupts and dynamically adjusts CPU affinity masks:
- Dynamic Load Balancing: Balances high-frequency hardware interrupts across CPU cores to avoid overheating or saturating a single physical core.
- Cache Domain Awareness: Groups related interrupts within the same CPU cache domain (L2 or L3 cache) to minimize cache thrashing.
- CPU Core Banning: Permits administrators to ban specific CPU cores from receiving hardware interrupts, isolating those cores exclusively for dedicated user-space application threads (such as DPDK or database engines).
Checking Service Status and Installed Version
Verify that irqbalance is installed and currently running on your Ubuntu Server:
systemctl status irqbalance.service
If the service is not currently installed, install it using apt:
sudo apt-get update && sudo apt-get install -y irqbalance
Confirm the installed daemon version:
irqbalance --version
Inspecting Current Hardware Interrupt Distribution
To evaluate how hardware interrupts are currently balanced across CPU cores, inspect /proc/interrupts:
head -n 25 /proc/interrupts
To monitor interrupt generation rates per core in real time, use mpstat from the sysstat package:
mpstat -I SCPU 1 5
The output shows softirq and interrupt activity across each logical core. If core 0 shows 100% saturation while remaining cores remain idle, irqbalance configuration adjustments are necessary.
Configuring irqbalance Defaults
On Ubuntu, the irqbalance systemd service reads configuration options from /etc/default/irqbalance. Open the configuration file in an editor:
sudo nano /etc/default/irqbalance
The default configuration file typically contains commented options:
# Configuration for the irqbalance daemon
# Enable or disable the daemon: "1" = enabled, "0" = disabled
ENABLED="1"
# Balance mode: "oneshot" balances once at boot and exits; default is continuous daemon
# ONESHOT="0"
# Arguments passed to the daemon
# OPTIONS=""
Banning Specific CPU Cores from Interrupts
When pinning high-performance database threads or containerised workloads to specific CPU cores, you must prevent irqbalance from assigning hardware interrupts to those cores. This is achieved by declaring a hexadecimal CPU mask via IRQBALANCE_BANNED_CPUS.
Calculating the Hexadecimal CPU Bitmask
Each bit in the mask corresponds to a logical CPU core (Bit 0 = CPU 0, Bit 1 = CPU 1, Bit 2 = CPU 2, etc.):
| Target Banned Cores | Binary Representation | Hexadecimal Bitmask |
|---|---|---|
| CPU 0 only | 00000001 |
00000001 |
| CPU 1 only | 00000010 |
00000002 |
| CPU 2 and CPU 3 | 00001100 |
0000000c |
| CPU 4, 5, 6, and 7 | 11110000 |
000000f0 |
For example, to reserve CPU cores 2 and 3 exclusively for application workloads and ban them from receiving interrupts, add the following line to /etc/default/irqbalance:
IRQBALANCE_BANNED_CPUS="0000000c"
On high-core-count NUMA systems with more than 32 logical cores, separate 32-bit words with commas (e.g. 00000000,0000000c).
Tuning Polling Interval and Power Management
By default, irqbalance re-evaluates interrupt loads every 10 seconds. In bursty high-frequency network environments, a shorter interval (e.g. 2 to 5 seconds) provides faster adaptation:
OPTIONS="--polldelay=5 --deepestcache=2"
The --deepestcache argument instructs irqbalance to group interrupts within specific cache levels (such as L2 cache) to maximize memory locality.
Applying Configuration Changes and Verifying Affinity
After saving adjustments in /etc/default/irqbalance, restart the service:
sudo systemctl restart irqbalance.service
Verify that the daemon process launched with the specified arguments:
ps aux | grep irqbalance
To confirm that banned cores are no longer receiving interrupts, inspect the affinity masks of critical networking interrupts in /proc/irq/:
cat /proc/irq/$(grep eth0 /proc/interrupts | awk -F: '{print $1}')/smp_affinity
The returned hexadecimal mask will exclude the bits corresponding to your banned CPU cores, confirming that hardware interrupts are routed exclusively across allowed cores.
By properly tuning irqbalance on Ubuntu Server, systems engineers achieve deterministic latency, prevent core saturation, and optimize CPU cache utilisation across multi-threaded enterprise workloads.