newsfilter.io
Conference Presentation

System Jitter and Where to Find It: A Whack-a-Mole Experience

Benchmark Scenario & Initial Setup

  • The presentation analyzes a "toy" distributed message passing system using two processes (pinger/ponger) and ring buffers on a single machine to simulate market data processing.
  • The system architecture consists of two ring buffers: one for Pinger-to-Ponger and one for Ponger-to-Pinger, where the value increments with each round trip.
  • The benchmark measures round-trip latency ($t_2 - t_1$) on a virtualized Intel Cascade Lake server (3.6 GHz) running OCaml, a language with a fundamentally single-threaded runtime requiring multi-process parallelism.
  • Initial unoptimized virtualized measurements yielded a median latency of 637 nanoseconds with jitter as high as 16 microseconds.

Optimization Strategies & Results

1. Hardware Isolation (Bare Metal)

  • Removing the virtualization layer to run on bare metal reduced median latency from 637ns to 223ns, eliminating significant "noisy neighbor" noise from other virtual machines.
  • Despite this improvement, a distinct latency tail around 1 microsecond remained, indicating kernel-level interference.

2. Interrupt Isolation (isolcpus)

  • Investigation via Intel Processor Trace revealed that network interrupts from the ixgbe driver were interrupting the application cores.
  • Configuring the kernel parameter isolcpus isolated specific cores (e.g., cores 1 and 2) from network interrupts.
  • This change required manually assigning processes to cores via taskset since the scheduler would no longer migrate tasks on isolated cores.
  • Removing network interrupt interference reduced median latency from 223ns to 194ns.

3. Timer Tick Reduction (nohz_full)

  • Profiling identified local timer interrupts (occurring ~1,000 times/second) as the cause of the remaining 1-microsecond tail, used for process scheduling and frequency scaling.
  • Setting the kernel parameter nohz_full reduced the timer interrupt frequency from 1,000 Hz to once per second.
  • This optimization cut latency by an additional 24 nanoseconds (median now ~170ns) and virtually eliminated the 1-microsecond spike.

4. Turbo Boost Management

  • Analysis of the frequency vs. time plot revealed a "sawtooth" pattern caused by the CPU oscillating between base frequency (3.6 GHz) and Turbo Boost frequency (4.4 GHz).
  • Frequency transitions introduce variable latency and jitter.
  • Disabling Turbo Boost forced the CPU to run at a constant 3.6 GHz.
  • This trade-off removed jitter entirely but increased the median latency by 1 nanosecond due to the lower base clock speed.

5. Micro-architectural Optimization (Speculative Execution)

  • Intel's OPCM tool attributed 8% of pipeline stalls to "bad speculation," where the CPU incorrectly assumed loop conditions would remain false and issued redundant loads.
  • The root cause was the lack of a hint in the tight spin-loop, causing the CPU pipeline to stall upon correct loop exit.
  • Introducing the x86 pause instruction via a compiler intrinsic (one line of OCaml code) reduced bad speculation from 8% to 1%.
  • This change reduced median latency to 163 nanoseconds and collapsed the remaining latency peaks.

6. Hardware Overclocking (Risk Assessment)

  • Running on overclocked hardware with faster RAM and higher CPU clocks reduced latency by an additional 94 nanoseconds compared to the optimized baseline.
  • However, testing revealed that aggressive overclocking led to memory corruption ("1 + 1 = 3") and system instability in real trading systems.

Final Metrics & Trends

  • The optimization journey reduced median latency from 637ns (jitter 16µs) to 163ns (jitter near zero), an order-of-magnitude improvement.
  • The final optimized system demonstrates a high correlation between median and p99 latencies, making any future performance regression immediately visible.
  • Virtualization remains a primary source of jitter; bare metal or dedicated metal instances (e.g., AWS EC2 Metal) are recommended for deterministic low-latency systems.
  • Running Docker on bare metal is viable provided the application does not rely on heavy system calls, as Docker's namespace isolation introduces negligible jitter compared to full virtualization.
  • The "frog in boiling water" effect is a major risk: high-jitter systems can degrade performance by 10x without triggering detection, whereas deterministic systems alert developers to regressions instantly.