Table of Contents
Valgrind callgrind
callgrind is a profiling tool built on Valgrind's instrumentation engine. Unlike perf, which samples at fixed intervals, callgrind counts instructions deterministically—every instruction is counted. This gives reproducible results even for very short-running programs.
valgrind --tool=callgrind ./program callgrind_annotate callgrind.out.12345
perf record is fast but requires many samples to be statistically accurate. callgrind is slower but deterministic—perfect for analyzing short-lived test cases or programs where sampling might miss small but important functions.
Generating profiles:
valgrind --tool=callgrind --dump-instr=yes ./program # detailed instruction counts callgrind_annotate callgrind.out.PID
By default, callgrind records per-function instruction counts and call graphs. --dump-instr=yes adds per-instruction counts (larger data file, more detail).
Output: callgrind_annotate displays the call graph sorted by instruction count. Each line shows a function, number of instructions executed, and number of times it was called:
Ir Calls Fn name
1,234,567 5,000 main
1,000,000 1,000 process
500,000 1,000 compute_kernel
250,000 1,000 matrix_multiply
“Ir” is instruction references (instructions executed). This shows main executed 1.2M instructions and called process 5000 times.
Advantages over perf: 1. Deterministic: same results every run (no sampling noise) 2. Complete: captures every instruction, never misses small functions 3. Reliable: short programs that don't generate enough samples under perf are profiled accurately
Disadvantages: 1. Slow: 10-50x overhead from instrumentation 2. Not real-time: can't profile production workloads 3. Memory-heavy: large programs produce gigabyte-sized profile files
Use cases: Test suite profiling, understanding performance of short algorithms, verifying that optimizations are effective (deterministic comparisons), profiling on systems where perf isn't available.
Comparing callgrind profiles:
valgrind --tool=callgrind --outfile=profile1.out ./program_v1 valgrind --tool=callgrind --outfile=profile2.out ./program_v2 callgrind_annotate profile1.out profile2.out
This compares two profiles side-by-side, showing which functions changed performance.
