Skip to content

Low-latency C++ interview questions

By the Mockich team · Updated · 6 sources

Low-latency C++ questions test whether you know what code costs on real hardware: where the data sits relative to the cache, what allocates, which branches are unpredictable, and what two threads touching nearby memory do to each other. A strong answer names the mechanism, gives an order of magnitude, says how you would measure it, and states the trade-off of the fix.

Key points

  • Talk in costs: a cache miss, an allocation, a mispredicted branch, a contended cache line.
  • Layout often matters more than the algorithm on hot paths. Say how the data sits in memory.
  • Keep allocation and locks off the hot path; say what you would preallocate.
  • Use the weakest memory ordering that is correct, and say why it is correct.
  • Measure percentiles from a histogram: tail latency is what the business feels.

The costs to know, as orders of magnitude

Interviewers do not expect exact cycle counts, and they vary by processor. They do expect the ordering and the rough gaps: a hit in the first-level cache takes a few cycles, about a nanosecond; a trip to main memory is on the order of 100 nanoseconds; a mispredicted branch costs on the order of 10 to 20 cycles on a modern out-of-order core. A cache line is 64 bytes on most x86-64 processors. Say “order of magnitude” when you quote these, and say you would measure on the target machine.

Sources: [2], [4]

Worked example: data layout

An order book side holds 1,000 resting orders, each a 48-byte struct with price, quantity, order id, timestamps and flags. A loop that scans only the prices to find the best level touches all 48,000 bytes, about 750 cache lines, because each price sits next to fields the loop never reads.

Store the 8-byte prices in their own contiguous array (structure of arrays) and the same scan touches 8,000 bytes, about 125 cache lines, and the hardware prefetcher sees a simple stride. The trade-off: code that needs a whole order now reads from several arrays, and inserts touch several of them. Say both sides; the interviewer will ask.

Sources: [2], [5]

Questions that come up, with short answers

  • Why avoid allocation on the hot path? A general-purpose allocator can take a lock, touch cold memory or fault in a new page, so its cost is unpredictable. Preallocate, reserve containers up front, or use pools; std::pmr resources (C++17) make arena allocation explicit.
  • What does a virtual call cost? An indirect call through the vtable, usually well predicted when one type dominates; the bigger cost is that the compiler cannot inline across it. Alternatives: final classes, templates (CRTP) or std::variant with std::visit when the set of types is closed.
  • What is false sharing? Two threads write different variables on the same cache line, so the line bounces between cores although no data is shared. Pad or align hot per-thread data to separate lines, for example with alignas(64) or std::hardware_destructive_interference_size where the compiler provides it.
  • Branch prediction: sort or partition data so a condition is predictable, or replace a hard-to-predict branch with arithmetic when both sides are cheap. Measure first; compilers already do some of this.
  • Why is std::map slow on a hot path? Each node is a separate allocation, so a lookup chases pointers across memory. A sorted vector or a flat hash map keeps keys contiguous.

Sources: [1], [2], [3]

Memory ordering: a single-producer, single-consumer queue

The classic deep dive is a ring buffer between one producer thread and one consumer thread. The producer writes the element into its slot, then publishes the new tail index with a release store. The consumer reads the tail with an acquire load; if the slot is ready it reads the element, then publishes the new head with a release store, which the producer reads with an acquire load to check for space.

Release and acquire are enough because each index has one writer and the pairing makes the element write visible before the index that announces it. Sequential consistency would also be correct but can cost more; on x86-64 a sequentially consistent store usually compiles to a locked instruction or a fence, while a release store is a plain move. Keep head and tail on separate cache lines to avoid false sharing between the two threads, and use a power-of-two capacity so the index wraps with a mask.

Sources: [1], [6]

How it sounds out loud

Answering “how would you make this queue faster?”
“First I’d measure: a histogram of enqueue-to-dequeue latency, p50, p99 and p99.9, after a warm-up, with both threads pinned to cores.”
“Then the usual suspects: head and tail sharing a cache line, so I’d align each to 64 bytes; and sequentially consistent atomics where acquire and release are enough.”
“The trade-off of padding is memory and a slightly bigger structure, which is fine here because there is one queue per pair of threads.”

Measuring latency

  • Report percentiles from a histogram: the median says little about the slow requests that cost money.
  • Warm up caches and branch predictors before recording, and pin threads to isolated cores so the scheduler does not move them.
  • Use a monotonic clock (std::chrono::steady_clock) or the processor’s timestamp counter, and subtract the cost of reading the clock itself.
  • Watch for coordinated omission: a load generator that waits for each reply before sending the next hides the queueing delay real traffic would see.

Sources: [5], [6]

Common mistakes

  • Quoting precise cycle counts as facts instead of orders of magnitude to be measured.
  • Choosing a data structure for its big-O and ignoring how it sits in memory.
  • Reaching for lock-free code before measuring whether a lock is the bottleneck.
  • Using memory_order_relaxed where a happens-before relation is needed.
  • Reporting average latency only.
  • Proposing an optimization without its cost: memory, complexity or portability.

Sources: [2], [5]

Questions

Do I need to know assembly for low-latency C++ interviews?

Reading a little helps, for example to see whether a call was inlined or a store has a fence. Most questions are about mechanisms and trade-offs, not writing assembly.

Which C++ standard should I know?

C++17 and C++20 features come up most: std::optional, std::variant, std::span, concepts and the atomics library. Know where each fits on a hot path.

How should I answer when I do not know a number?

Give the order of magnitude you are confident in, say what it depends on, and say how you would measure it on the target machine.

Practise this out loud with Vera

Mockich’s C++ deep dive is the quant track’s fundamentals round: 35 min, six questions at regular and five at lead on data layout, move semantics, undefined behavior, templates, memory ordering and the systems around a trading engine, asked out loud with no code to read. Vera probes each answer once or twice for depth and gives at most one small hint. The report scores accuracy, depth, practical judgment, communication (plus breadth and connection at lead) and quotes what you said.

Sources

We read these sources on 2026-11-03 and checked the memory-ordering and interference-size statements against cppreference; the order book example, its numbers and the spoken lines are our own.

  1. [1] cppreference.com, cppreference.com: std::memory_order and std::hardware_destructive_interference_size (CC BY-SA 3.0)
  2. [2] XiaoXKKK on GitHub, CPP-Quant-Offer (C++ and low-latency knowledge base) (MIT)
  3. [3] Anthony Calandra, Modern C++ features (C++11 to C++23) (MIT)
  4. [4] techinterview.org, C++ for Quants: What HFT and Low-Latency Firms Test in C++ Interviews
  5. [5] quantt.co.uk, Quant developer interview questions
  6. [6] techinterview.org, The lock-free queue question every HFT interview comes back to