Quant developer HFT course · Module 6: The operating system
CPU isolation, real-time scheduling and kernel bypass
The question
You have a server for the trading system. How would you configure the machine so the strategy thread is never interrupted?
The goal
A pinned, spinning thread can still be interrupted by the scheduler, the timer tick, device interrupts and kernel housekeeping (lesson 3). Isolation means arranging the machine so that on the hot thread's core, nothing else ever runs.
The kernel settings
On the kernel command line:
isolcpus=(or cpusets/cgroups). Removes the listed cores from the general scheduler's load balancing, so ordinary threads are not placed there. Threads must then be pinned to those cores explicitly. Newer setups often prefer cgroup v2 cpusets with isolated partitions, which can be changed without a reboot.nohz_full=. Stops the periodic timer tick on the listed cores while they run a single task. Without it, every isolated core is still interrupted hundreds or thousands of times a second.rcu_nocbs=. Moves RCU callback processing off those cores to housekeeping cores.- IRQ affinity. Each device interrupt has an affinity mask in
/proc/irq/<n>/smp_affinity. Point them all at the housekeeping cores, and stopirqbalancefrom moving them back. The network card's interrupts go where the network-handling thread wants them, or nowhere if the card is polled (below). - Kernel worker threads and work queues can be confined with
/sys/devices/virtual/workqueue/cpumaskand similar settings.
The BIOS and power settings
The processor's own power management adds latency:
- C-states: idle cores enter sleep states and take microseconds to wake. Spinning threads keep their own core awake, but limiting deep C-states (in BIOS, or
processor.max_cstate,intel_idle.max_cstate, or by holding/dev/cpu_dma_latencyopen at 0) avoids wake-up delays elsewhere. - Frequency scaling: set the governor to
performanceand fix the frequency, so cores do not ramp up and down. - Turbo: higher peak frequency, less predictable; teams decide either way and measure.
- Hyper-threading: often disabled, or the sibling of each hot core left idle.
- SMIs (system management interrupts) from firmware are invisible to the OS and steal time; vendors provide low-latency BIOS profiles that reduce them, and tools like
hwlatdetectmeasure them.
Real-time scheduling
Linux offers real-time policies, SCHED_FIFO and SCHED_RR, whose threads always run in preference to normal ones. It is tempting to make the hot thread SCHED_FIFO at high priority. On an isolated core, it matters little: nothing else is meant to run there. On a shared core, a spinning SCHED_FIFO thread starves everything below it, including kernel threads that the system needs, which can hang the machine; the kernel's real-time throttling (sched_rt_runtime_us) exists to prevent exactly that and introduces its own pauses. The common advice is: isolate and pin first; use real-time priority deliberately and sparingly, not as a substitute for isolation.
Kernel bypass
Even on an isolated core, receiving a packet through the Linux network stack involves an interrupt, kernel processing and a copy into the socket buffer, then a system call to read it. Kernel bypass removes the kernel from the data path: the network card's receive queues are mapped into the process, and a thread polls them directly in user space.
- Solarflare/AMD Onload intercepts ordinary socket calls and serves them from a user-space stack, so existing code can use bypass unchanged; its lower-level API, ef_vi, exposes the raw queues.
- DPDK gives full control of the card from user space, with its own packet buffers and poll-mode drivers, at the cost of writing your own protocol handling.
- Mellanox/NVIDIA VMA and RDMA-based approaches play similar roles on their hardware.
The thread that polls the card is the network-handling thread from the core diagram; there are no interrupts and no system calls on the receive path. Module 7 goes into the network side.
Proving it
Configuration drifts. Teams verify isolation with measurements: a tool that spins on each isolated core and records any gap in its own execution longer than a threshold (the principle behind hwlatdetect, sysjitter and osnoise) run before the open, plus per-thread context switch and interrupt counts exported as metrics during the day.
Check yourself
Question 1 of 3
What does nohz_full do for an isolated core?
Without it, the tick keeps interrupting every core. nohz_full removes it when there is only one runnable task, which is the isolated-core case.
Question 2 of 3
Why is running a spinning thread with SCHED_FIFO on a shared core dangerous?
A real-time spinner monopolises its core. On an isolated core that is the intent; elsewhere it can starve the system, and RT throttling then pauses it instead.
Question 3 of 3
What does kernel bypass remove from the receive path?
The application polls the card's receive queues directly in user space. Protocol parsing and loss handling are still the application's job.
In the interview
Say your own answer out loud first, then open the one we would give.
How do you isolate a core for a latency-critical thread on Linux?
Remove it from general scheduling with isolcpus or an isolated cpuset, stop the timer tick with nohz_full, move RCU callbacks and kernel work queues off it, route every interrupt to housekeeping cores and disable irqbalance, pin the thread to it, and keep its hyper-thread sibling idle. In the BIOS, limit deep C-states, fix the frequency and use a low-latency profile.
Would you run the trading thread with SCHED_FIFO?
Only on a properly isolated core, and then it adds little. On a shared core, a spinning real-time thread starves kernel threads and can trigger RT throttling, which itself causes pauses. Isolation and pinning are the real tools.
What is kernel bypass?
Letting the application read and write the network card's queues directly from user space and poll them, instead of going through interrupts, the kernel stack and system calls. Onload does it behind the socket API; ef_vi and DPDK expose the queues directly.
How do you know the isolation works?
Measure it: run a jitter detector on the isolated cores to record any interruption above a threshold, and export per-thread involuntary context switches and per-core interrupt counts during the day.