5.3.16 · D2Build Systems & Toolchain

Visual walkthrough — Profiling — gprof, perf, Valgrind - Callgrind

2,005 words9 min readBack to topic

We are deriving the central result of the parent note: Every symbol will be earned before it is used.


Step 1 — What "running a program" actually looks like in time

Figure — Profiling — gprof, perf, Valgrind - Callgrind

The true answer we want is : literally, add up the lengths of every red band. A perfect tool would do exactly that. The problem: measuring every band edge exactly is expensive (that is instrumentation, and it distorts timing). So we cheat cleverly.


Step 2 — The cheat: don't measure, photograph

Figure — Profiling — gprof, perf, Valgrind - Callgrind

Read the picture: if there were clicks and of them landed on the red band, then compute_dist "caught" 4 out of 10 clicks.


Step 3 — Each click is a little ruler of length

Figure — Profiling — gprof, perf, Valgrind - Callgrind

Step 4 — Rewrite it as a fraction (the form you'll actually read)

Figure — Profiling — gprof, perf, Valgrind - Callgrind

Step 5 — Why it's only approximate: the wobble of small counts

Figure — Profiling — gprof, perf, Valgrind - Callgrind

Step 6 — The degenerate cases (never leave the reader stranded)

Figure — Profiling — gprof, perf, Valgrind - Callgrind

The one-picture summary

Everything above collapses into one image: a timeline, evenly-spaced red clicks, red clicks counted into , divided by , multiplied by , out comes the self time. Trace the arrows.

Figure — Profiling — gprof, perf, Valgrind - Callgrind
Recall Feynman retelling — the whole walkthrough in plain words

Picture your program's run as a long ruler laid on the floor, painted in coloured stripes — each stripe is time spent inside one function, and the stripe we care about is red. We don't want to measure every stripe edge (too fussy, and touching it disturbs the timing). So instead we set a metronome that ticks every seconds. On each tick we glance down and note which colour we're standing on. Count the red ticks () and all the ticks (). Since ticks are evenly spaced, each tick "owns" a slice of floor, so red time ≈ (red ticks) × . Dividing by the whole thing lets vanish, leaving a clean fraction of ticks — that's the "% time" your profiler prints. It's only an estimate because a tick can miss a thin stripe entirely (that's why a function can show 0%); take more ticks and the wobble shrinks like ; take infinitely many and you get Callgrind's exact answer.

Recall Quick self-check

Why does disappear from the final formula? ::: Both self time () and total time () carry one factor of , so it cancels in the ratio . A function shows 0 self samples — is its true time zero? ::: No. A fast function can fall entirely between two clicks and be missed; raise the rate or use exact-count Callgrind. To halve the statistical error of a percentage, how many more samples? ::: About 4× more, because error scales like . The limit of this picture corresponds to which tool? ::: Callgrind — exact, deterministic counts, at 20–100× slowdown.

Related: Compiler Optimization Flags (-O2, -O3, inlining) · Cache Hierarchy & Locality of Reference · Branch Prediction & Pipelining · Debugging with gdb · Build Systems & Toolchain