Skip to content
tezvyn:
Menu

Profiling a Rust hot loop with perf

Source: interviewHardHow cards are made

Summary

low-level performance profiling.

Key points

build with debuginfo, perf record cycles or cache-misses, perf report then perf annotate to map counters to source/asm; flamegraph for hotspots.

What's really being asked

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.

The full answer

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.

The mistakes people make

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.

What usually comes next

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?

A 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.

Interview question

Before using perf annotate to map cache-miss counters to Rust source, what build configuration is essential?

  • a.A build with all optimizations disabled and LTO on
  • b.A debug build so the optimizer does not change the code
  • c.A release build with debug symbols enabled so perf can map addresses to source linesCorrect
  • d.Any build, since perf reads source files directly without symbols
Why?

You profile optimized release code but must keep debug symbols so perf maps sampled addresses back to functions and lines. A debug build distorts hotspots, and perf needs symbol info, not raw source access.

Just read this? Test yourself on what you have been reading.

Read the original → rust-lang.github.io

Put your scrolling time to good use

Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Open roles that interview on rust — each one lists the topics its interview covers.

See open roles