In high-concurrency, low-latency network scenarios like caching services, message queues, and web proxies, network interrupt handling can become a system bottleneck as both Hardware Interrupts (Hard IRQs) and Software Interrupts (Soft IRQs) compete with application logic for vCPU resources. Pinning network interrupt handling and application processes to separate vCPU cores significantly reduces context switches, cache pollution, and scheduling delays, improving overall throughput and tail latency. This guide provides a general method for optimizing vCPU pinning on Alibaba Cloud Elastic Compute Service (ECS) instances. For example, testing on a g9i.8xlarge instance with Alibaba Cloud Linux 3 showed that separating Redis worker threads from network interrupts increased Queries Per Second (QPS) by 26%.
Use cases
This optimization is recommended for the following use cases:
The application is both CPU-intensive and network I/O-heavy, such as Redis, Kafka, Nginx, or a MySQL Proxy.
The application runs on a multi-core Elastic Compute Service (ECS) instance with 16 or more vCPUs.
You observe a high percentage of CPU time spent on
irqorsoftirqon the cores where the application process is running. You can check this usingmpstat.
This optimization is not recommended for the following scenarios:
Small instances with fewer than 8 vCPUs.
Mixed deployments with multiple high-load services.
Containerized environments, unless CPU resource isolation is configured with tools like the Kubernetes CPU Manager or cgroups.
How it works
Linux network packet processing involves two key stages:
Hardware Interrupt (Hard IRQ): The Network Interface Card (NIC) receives a packet and triggers a vCPU interrupt that the driver then handles.
Software Interrupt (Soft IRQ): The kernel protocol stack, such as
NET_RX, processes the packet in the context ofksoftirqdor NAPI.
Sharing cores with application threads can cause:
L1/L2 Cache Pollution
Frequent flushing of the vCPU pipeline
Increased scheduling latency
Using IRQ affinity and Receive Packet Steering (RPS) confines interrupt handling to a dedicated set of vCPUs, allowing application threads to exclusively use the remaining cores and achieve resource isolation.
RPS is a software mechanism in the Linux kernel that distributes packets received from a single-queue NIC across multiple vCPU cores for parallel processing during the software interrupt stage. This overcomes single-core bottlenecks and improves network throughput.
Configuration steps
Step 1: Plan the vCPU partition
This example uses an instance with 32 vCPUs (vCPU 0–31):
Purpose | vCPU range | Recommended vCPU cores |
Application process | vCPUs 0–7 | 8 or more (adjust based on the number of application threads) |
Network Interrupt Handling | vCPUs 8–31 | 8 or more (more cores are needed for more queues) |
Step 2: Bind Hard IRQs to dedicated vCPUs
This example uses the primary network interface eth0, which uses the virtio driver:
# Get the interrupt numbers for the virtio device corresponding to eth0 (e.g., virtio1)
IRQS=$(grep 'virtio1-' /proc/interrupts | cut -d: -f1 | tr -d ' ')
# Calculate the vCPU mask: vCPUs 8–31 correspond to the hexadecimal mask ffffff00
# For a 32-core system (0–31), this mask sets bits 8 through 31 to 1.
for irq in $IRQS; do
echo ffffff00 > /proc/irq/$irq/smp_affinity
doneStep 3: Enable RPS load balancing
RPS prevents single-core bottlenecks by distributing received packets to multiple vCPUs for software interrupt processing:
# Set the RPS vCPU mask for each RX queue to match the IRQ mask
for rps_file in /sys/class/net/eth0/queues/rx-*/rps_cpus; do
echo ffffff00 > "$rps_file"
doneStep 4: Bind the application to dedicated vCPUs
# Pin the Redis process to vCPUs 0-7 on startup
taskset -c 0-7 redis-server /etc/redis.confExample: Improving Redis Performance
Deploying Redis 6.2 on a g9i.8xlarge (32 vCPU) instance yielded the following results:
Configuration | QPS (GET) |
Default (no pinning) | 195K |
Optimized | 246K (+26%) |
Test command:
./memtier_benchmark -s $SERVER_IP -p $port -t 8 --test-time=60 -c 10 --ratio=0:1 --pipeline=1 -d 32 --key-maximum=100000Key observation:
mpstatshowed that the%irqand%softvalues on application cores dropped to nearly zero.
Verify the optimization
mpstat -P ALL 1Before pinning:

After pinning:
