A strong answer
A naive C++ loop timed with a single start/stop timestamp almost always measures the wrong thing due to four pitfalls:
- Compiler dead-code elimination and constant folding: At
-O2or-O3, if the result of the loop is never observed outside the loop, the compiler proves the computation has no side effects and deletes the entire loop (or hoists invariant math outside the loop), reporting a bogus0 nsper operation. You must feed outputs into an opaque sink (DoNotOptimizeviavolatileor emptyasm volatile("" : : "r,m"(val) : "memory")) andClobberMemory()so the compiler cannot delete or pre-compute the work. - Cold start vs steady state: The very first iteration triggers OS minor page faults (zero-filling newly mapped 4 KB pages), cold L1/L2/L3 caches, unprimed branch predictors, and idle CPU turbo frequency states. Always run untimed warmup iterations before starting the clock.
- Wrong clock:
std::chrono::system_clockcan jump forward or backward when NTP adjusts system time (And on some standard librarieshigh_resolution_clockis just an alias forsystem_clock). Always time intervals withstd::chrono::steady_clock, which is guaranteed to be monotonic. - OS scheduling noise and thermal drift: A single run can be skewed by an OS context switch, interrupt, or CPU thermal throttling. Run many trials, interleave competing implementations (
A, B, A, B), and report the median and spread (e.g., p10/p90 or IQR) rather than a single number or an outlier-sensitive mean.
What the interviewer is listening for
- Explains how
-O3eliminates unused work and howDoNotOptimize/ volatile sinks prevent it without crippling register allocation inside the timed body. - Chooses
std::chrono::steady_clockand explains whysystem_clockis unsafe for duration measurements. - Insists on warmup runs, multiple interleaved trials, and distribution metrics (median + spread).
Common mistakes
- Benchmarking a
-O0debug build, which measures stack-load/store overhead and uninlined STL wrapper calls rather than real production machine code. - Including test fixture allocation or random number generation inside the timed region when only the algorithm itself should be measured.