🎓 A1Learner
🔍

Rust Profiling

A profiler is a tool that watches a running program and reports which functions ate the time. A profiler names the real slow spot.

Build for profiling

Keep release speed, but keep the line information a profiler needs:

// Cargo.toml
[profile.release]
debug = "line-tables-only"

Record with samply

samply runs your program and opens a visual profile in the browser:

samply record ./target/release/my_app

On Linux: perf plus a flame graph

perf records the samples, cargo flamegraph draws them:

perf record -g ./target/release/my_app
cargo flamegraph

Hunting allocations with DHAT

When the question is "who keeps allocating?", DHAT counts every allocation and names the line:

valgrind --tool=dhat ./target/release/my_app

Example

fn count_letters(text: &str) -> usize { text.chars().filter(|c| c.is_alphabetic()).count() }
fn count_words(text: &str) -> usize { text.split_whitespace().count() }
fn main() {
    let mut text = String::new();
    for _ in 0..10_000 { text.push_str("rust makes fast programs "); }
    println!("words = {}", count_words(&text));
    println!("letters = {}", count_letters(&text));
    println!("bytes = {}", text.len());
}

Key points

  • Profiler: a tool that watches a running program and reports where the time or memory went
  • Profile a release build: a debug build has different hot spots and teaches the wrong lesson
  • Sampling profiler: it checks what the program is doing many times a second
  • It builds the picture from samples
  • samply and perf work this way
  • Use cargo flamegraph to draw the picture as a flame graph
  • The wider a function's box, the more time it is eating
  • Its calls count towards that time, too
  • Use DHAT when allocations are the question: it reports exactly which lines allocated, how often, and how much
  • The Rust Performance lesson set the rule, measure before changing anything.

In this example, main builds one big text and counts it two ways. The text holds 10,000 copies of a 4-word sentence. That is 250,000 bytes. A profiler would point straight at count_letters. It walks every character of the text. count_words only hops from space to space. That is the profiler's whole job — it names the function to look at first, before you change a single line.

Note

A profiler shows where time goes, not why

Read the wide boxes first, form one idea, change one thing, and measure again

Try it Yourself

Edit the code, then press Run.

Running is simulated · Rust Playground

Exercise

Your release program is slow and you do not know where. What is the first move?