Command-line analysis of puffin profiles, built for AI agents and scripts instead of
eyeballing a flamegraph. It reads .puffin files, including ones saved from puffin_viewer, and records from live
puffin_http servers. Every command prints compact text by default. Add --json to get structured output. All times are in ms.
cargo install --path .
puffin-cli record -o before.puffin --seconds 5 # app must run puffin_http::Server (default 127.0.0.1:8585)
puffin-cli frames before.puffin # frame time mean/p50/p90/p99/max, threads, slowest frames
puffin-cli scopes before.puffin --skip 60 --sort self # flat profile: ms/frame, self, max, calls/frame, per-call
puffin-cli tree before.puffin --frame slowest --depth 3 # call tree of the worst frame (or `all` = average frame, or an index)
# ...optimize, re-record...
puffin-cli diff before.puffin after.puffin # per-scope ms/frame change, biggest movers firstLive view of a running app:
puffin-cli watch # top-like screen redrawn every second, Ctrl-C to quit
puffin-cli --json watch --count 10 --interval 0.5 # JSONL: one {t_s, fps, frame_ms, scopes} object per windowEach update covers only the frames from the last window, so spikes show up instead of being averaged away.
Filters shared by the analysis commands are --thread <substring> and --skip <n>. --skip drops warm-up and loading frames.
The app being profiled needs:
let _server = puffin_http::Server::new("127.0.0.1:8585")?;
puffin::set_scopes_on(true);
loop {
puffin::GlobalProfiler::lock().new_frame();
// ... profile_function!() / profile_scope!() ...
}cargo run --example demo starts an instrumented fake game loop you can use to try it out.
The app's puffin_http protocol version has to match this build (puffin 0.20 / puffin_http 0.17, protocol v2).