Skip to main content
๐Ÿ“œ WAYPOINT LESSON

Measure First: Budgets, Sinks, and -O Levels

โญโญโญ advancedโณ 20 min read๐Ÿ“ Lesson 218 of 225

Optimization without measurement is decoration. The tools: monotonic clocks, iteration budgets, and keeping the optimizer honest.

The budget loop

Work backward from a time budget: if one iteration costs p milliseconds and you may spend B milliseconds, run ceil(B / p) iterations โ€” and guard division by zero. Deriving the iteration count from a budget (instead of a magic constant) is what makes a benchmark stoppable and comparable across machines.

Keeping the optimizer honest

volatile double sink = 0.0;          /* or accumulate-and-print */
for (size_t i = 0; i < iters; i++) sink += work(i);

Without a consumed result, the optimizer may delete the entire loop: computing a value nobody uses is not an observable behavior (module 2). The sink (or a printed checksum) makes the work real.

Optimization levels, honestly

  • -O0: fast compile, slow code โ€” the debugging mode. Variables live in memory; stepping in a debugger stays sane.
  • -O2/-O3: inlining, vectorization, aggressive reordering. Code may behave observably-identically while executing completely differently.
  • The gap between -O0 and -O2 on the same source is routinely large โ€” which is why "it felt slow in debug" is not a performance claim.

ISO C defines none of this: optimization levels are compiler flags (GCC/Clang here, labeled as such). Undefined behavior plus optimization equals module 4's menagerie โ€” measure with the flags you ship.

The regression habit

A number without a baseline is a anecdote. Keep the benchmark in the repo, record the machine, flags, and input; compare like with like. When a change claims 20%, re-run with and without. If the delta does not reproduce, it did not happen.