A lock-free C++20 matching engine, the low-latency backbone of a trading platform. This page is the methodology: I re-ran the committed benchmarks on one stated machine and commit, so every number here is one you can reproduce. The repository is private, so what follows is the design, the measurements, and the exact commands.
Everything below was measured on 2026-07-19 by re-running the committed Release binaries at one commit. Numbers are specific to this machine and toolchain.
Trading signals flow through a multi-stage pipeline, with the concurrency boundary drawn where it matters and each lock justified in the code:
std::atomic acquire/release ordering (not sequential consistency, which is a full fence on x86) because the producer/consumer relationship is one-directional. Head and tail sit on separate cache lines (alignas(64)) so the two cores do not bounce a shared line.shared_mutex (concurrent reads, exclusive writes).DeadlockDetector validates it at runtime and compiles to zero-cost no-ops in Release (#ifndef NDEBUG).Latency and throughput are two separate binaries, two separate experiments. I keep them apart.
bench_latency: 100,000 market buy orders against 1,000 resting sell limit orders (reseeded every 100), 4 engine threads. Each order is timed with std::chrono::high_resolution_clock from submit until its fill is drained by a tight spin. Percentiles are nearest-rank over recorded fills. About 99% of orders filled immediately (99,000 and 98,998 of 100,000 across two runs); percentiles are over those fills.
| Percentile | Run 1 | Run 2 |
|---|---|---|
| p50 | 0.9 µs | 0.9 µs |
| p90 | 1.2 µs | 1.2 µs |
| p95 | 1.2 µs | 1.2 µs |
| p99 | 2.3 µs | 2.1 µs |
| p99.9 | 25.5 µs | 27.4 µs |
| mean | 1.1 µs | 1.1 µs |
| max | 1.9 ms | 1.6 ms |
The millisecond max is the tail from the ~1% of orders that did not fill immediately and sat on the poll path. It is real, so I show it; p50 and p99 are over filled orders.
bench_queue_throughput: 10,000,000 ops per configuration, 16-byte items, wall time by high_resolution_clock, one timed run per invocation. I ran the binary three times for variance.
| Config | Run 1 | Run 2 | Run 3 |
|---|---|---|---|
| SPSC 1P:1C | 104.7M | 93.1M | 102.7M |
| MPMC 1P:1C | 79.4M | 77.6M | 79.7M |
| MPMC 4P:4C | 13.0M | 12.9M | 12.9M |
| MPMC 8P:8C | 10.9M | 10.5M | 10.5M |
SPSC throughput is ~93 to 105M ops/sec, median ~103M. MPMC throughput drops as producers and consumers contend on the shared ring, which is the expected shape.
Separate from performance, and fully reproduced.
| Check | Result |
|---|---|
| ctest suite | 11 / 11 passed (8 unit, 3 stress) |
| Zero lost (MPMC) | 100P × 100C × 10,000 = 1,000,000 items; asserts consumed == total → PASS (1,000,000 / 1,000,000) |
| FIFO (SPSC) | 1P/1C, 10,000,000 items, strict order check → PASS |
| Deadlock ordering | 50 threads, 50,000 mixed ops → 0 violations |
| ThreadSanitizer | no data races reported (Clang 18, Ubuntu 24.04 / WSL2, commit 499b60e; details below) |
The runtime deadlock detector is debug-only, so its violation-injection sub-test is skipped in the Release run.
Scoped to portability and correctness, not performance. WSL2 virtualization is fine for detecting races; I do not use it for latency or throughput claims.
<mutex> include, an in-class default argument relying on a nested struct's default member initializers, and std::result_of deprecation warnings from std::bind.Clang ThreadSanitizer reported no data races across the exercised unit and concurrency stress suites on Ubuntu 24.04 under WSL2, commit 499b60e: 11 of 11 tests, the 100P/100C MPMC and 10M-item SPSC stress, the 50-thread deadlock torture, and the shutdown regression run 20 times. ThreadSanitizer did not emit a deadlock report; the instrumented run changed scheduling enough to expose the hang.
From the engine package, at the stated commit:
cmake .. -G "Visual Studio 17 2022" -A x64 cmake --build . --config Release ctest -C Release --output-on-failure ./Release/bench_queue_throughput ./Release/bench_latency ./Release/stress_queue ./Release/stress_deadlock
Expected throughput output (abridged):
| Queue Type | Config | Ops/sec | Wall Time | | SPSC | 1P:1C | 102.7M | 97ms | | MPMC | 1P:1C | 79.7M | 125ms | | MPMC | 4P:4C | 12.9M | 775ms | | MPMC | 8P:8C | 10.5M | 950ms |
Expected stress output (abridged):
[STRESS] MPMC Queue: 100P/100C, 1000000 items Result: PASS (1000000/1000000 consumed) [STRESS] Lock ordering (50 threads, 50000 ops): PASS - 0 violations
An earlier version of this site quoted a higher SPSC throughput, a tighter p99, and a bare "ThreadSanitizer clean" label. Those probably came from a Linux/Clang build, but I could not recover the original output or environment, so I removed them rather than present numbers without a complete evidence chain. If I reproduce them on Linux I will publish both sets side by side as a cross-toolchain comparison, not as a rescue of the old headline.