Profiling a Rust hot loop with perf
low-level performance profiling.
build with debuginfo, perf record cycles or cache-misses, perf report then perf annotate to map counters to source/asm; flamegraph for hotspots.
WHAT THIS TESTS Whether you can profile Rust at the instruction and cache level using perf, set up symbols correctly, and interpret hardware counters to optimize a hot loop.
A GOOD ANSWER COVERS First build for realism: a release build, but enable debug symbols by setting debug = true or debug = 1 under profile.release so perf can map addresses back to functions and source lines. Optionally set codegen-units low for stable codegen. Then run perf record with hardware events: cycles and instructions to compute IPC, and cache-misses, cache-references, L1-dcache-load-misses, and LLC-load-misses to find memory-bound regions; for example perf record -e cycles,cache-misses ./target/release/app. Inspect with perf report to rank hot functions, then perf annotate or the report's annotate view to overlay sample counts onto the disassembly interleaved with source, revealing which instructions and lines burn cycles or miss cache. Cargo-flamegraph, which wraps perf, gives a quick visual of the hottest stacks.
COMMON WRONG ANSWERS Profiling a debug build, which has different codegen and misleading hotspots. Relying solely on criterion wall-clock benchmarks, which tell you something is slow but not why. Forgetting debug symbols, leaving perf with bare addresses. Ignoring frequency scaling, which skews cycle counts.
LIKELY FOLLOW-UPS What is a good IPC and what does a low one imply? How do you read a high cache-miss ratio, often a layout or access-pattern problem? How do branch-misses point to unpredictable branches? When do you reach for VTune or valgrind cachegrind instead, or counters via the perf_event interface?
ONE CONCRETE EXAMPLE A loop summing a column of a row-major matrix shows poor IPC and high LLC-load-misses in perf annotate, with samples concentrated on the strided load. The fix, iterating in row-major order or transposing, restores cache locality, which a subsequent perf record confirms by a sharp drop in cache-misses and a rise in IPC.
Read the original → rust-lang.github.io
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.