How to Configure irqbalance and Hardware Interrupt Distribution on Ubuntu Server

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.

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.