valgrind --tool=callgrind: Call-Graph Profiling
valgrind --tool=callgrind counts instructions and calls per function to build a precise call-graph profile.
Callgrind is deterministic: it counts every instruction rather than sampling, so results are reproducible across runs. That determinism is valuable for CI regression checks, at the cost of speed.
What it does
Callgrind instruments a program to count instruction executions and function calls, producing a callgrind.out file. callgrind_annotate summarizes it as text, and KCachegrind visualizes the call graph. Because it counts rather than samples, results are deterministic.
Common usage
valgrind --tool=callgrind ./my-program
callgrind_annotate callgrind.out.<pid>
# also simulate the cache
valgrind --tool=callgrind --cache-sim=yes ./my-programOptions
| Flag | What it does |
|---|---|
| --tool=callgrind | Select the Callgrind profiler |
| --cache-sim=yes | Simulate cache to report cache misses |
| --branch-sim=yes | Simulate branch prediction |
| --callgrind-out-file=<f> | Path for the output file |
| --dump-instr=yes | Collect per-instruction (not just per-line) costs |
In CI
Because callgrind is deterministic, the instruction count for a fixed workload is stable, so you can gate on it more reliably than on wall time. Store callgrind.out as an artifact and inspect with callgrind_annotate or KCachegrind offline.
Common errors in CI
Long runtimes are the usual failure; callgrind is even slower than Memcheck, so a small benchmark, not the full suite, is the right target. "callgrind_annotate: command not found" means the valgrind package that ships the helper is not installed. Multiple callgrind.out.<pid> files appear when the program forks; annotate the one for the main pid.