Quant developer HFT course · Module 8: Measuring latency
Drill: measuring and debugging
Measurement questions reward a method: say what you would measure, what result would confirm or refute each idea, and what you would do with it.
Prompt 1: How fast are we?
The interviewer says
How fast is our system? Give me a number.
Before you answer
Question · choose every correct option
Which belong in the answer? Choose all that apply.
One number cannot describe a distribution; the mean especially hides the tail.
Answers that lose the point
About 3 µs on average.
An average with no distribution, no method and no tail.
A strong answer
I would give a distribution rather than a number: p50, p99, p99.9 and the maximum of tick-to-trade, measured from the card's receive timestamp of the triggering packet to its transmit timestamp of the order, over a stated period and sample count. Alongside, per-stage percentiles from software timestamps on the same clock, so we can see where the time goes, and the processing time of all messages, not only those that trigger orders.
Lab replays tell us what the code can do; I would quote production numbers as the answer.
Prompt 2: The p99.9 regression
The interviewer says
After a release, p50 is unchanged but p99.9 doubled. How do you find out why?
Before you answer
Question · choose every correct option
Which approach is best? Choose all that apply.
Tail events are too rare for sampling profiles; per-event tracing is needed.
Answers that lose the point
Run perf record and look at the top function.
The top function describes the median, which did not change.
A strong answer
A sampling profile would mostly show the unchanged common case, so I would use the per-message stage timestamps: select the slowest 0.1% and see which stage grew compared with typical messages and with the previous release. Then look for what those messages share: message type, instrument, first touch of something, bursts, time of day.
In parallel I would correlate them with kernel events on that core, faults, switches and interrupts, using traces on the same clock. Once I have a candidate, I would reproduce it on a replay and diff the releases on exactly that path.
Prompt 3: Same work, slower
The interviewer says
Two versions of a function. perf stat shows the same instruction count but the new one takes 30% more cycles. What next?
Before you answer
Question · choose every correct option
What does this tell you? Choose all that apply.
Same instructions means same work; more cycles means less efficient execution.
Answers that lose the point
The compiler made it worse.
Possibly, but which mechanism, and how would you show it?
A strong answer
Equal instruction counts mean the work is the same, so the 30% is stalls: IPC fell. I would compare branch misses and cache misses at each level per thousand instructions between versions, and run top-down analysis to see whether the lost slots are bad speculation, memory bound or front-end bound.
That points at the mechanism: perhaps a field moved and a struct now spans two cache lines, or a branch became data-dependent, or code layout changed. Then I would confirm with perf mem or the assembly, fix it, and check the counters return.
Prompt 4: Memory bound
The interviewer says
The book update is memory bound. What do you do?
Before you answer
Question · choose every correct option
Which steps fit? Choose all that apply.
Hot-path memory problems are usually latency bound; the fix is layout, not parallelism.
Answers that lose the point
Buy faster memory.
Latency barely changes between memory parts; layout changes it by orders of magnitude.
A strong answer
First find the loads: perf mem sampling shows the instructions and data addresses of slow loads, which tells me which structure misses, and whether it is latency or bandwidth bound, which on a hot path is almost always latency.
Then reduce the number of distinct lines an update touches: flat arrays instead of nodes, hot fields packed together, cold fields moved out, price levels near the touch in a tick-indexed array. Verify with LLC misses per message, IPC and the book-update stage percentiles.
Prompt 5: Stops scaling
The interviewer says
Throughput stops increasing beyond four threads and CPU use is low. Diagnose.
Before you answer
Question · choose every correct option
Which are right? Choose all that apply.
Waiting threads are not on the CPU, so on-CPU profiles miss contention.
Answers that lose the point
Add more threads.
More threads, more waiting.
A strong answer
Low CPU and flat scaling mean threads are waiting rather than working, most often on a lock. An on-CPU profile would not show that, so I would use off-CPU profiling or futex tracing to find where threads block, and an instrumented mutex to get wait and hold times per call site.
Then fix the cause: shorten the long critical section, split or stripe the lock, replace read-mostly locking with snapshots, or move the data to a single owner fed by a queue, and confirm that throughput scales and wait times fall.
After the drill
Measurement is where interviews separate engineers who have done this from those who have read about it. Module 9 turns to the trading systems themselves, so you can talk about what the code is for.