# flamegraph-rs/flamegraph: Rust flamegraphs without Perl or pipes

> A cargo subcommand and standalone binary that turn perf, xctrace, dtrace or blondie samples into SVG flamegraphs. It is a thin, opinionated wrapper around Inferno, and the wrapper is where the interesting decisions live.

**flamegraph-rs/flamegraph** — Easy flamegraphs for Rust projects and everything else, without Perl or pipes <3

- Repository: https://github.com/flamegraph-rs/flamegraph
- Stars: 6,032 · Forks: 194
- Language: Rust
- License: Apache-2.0
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/flamegraph-rs-flamegraph

## What flamegraph-rs/flamegraph actually replaces

The original flamegraph tooling from Brendan Gregg is a set of Perl scripts that consume folded stack output from perf, dtrace or another sampler. Using it means knowing the sampler's flags, piping its output through stackcollapse-perf.pl, and then through flamegraph.pl. The project README describes its own value proposition in one line: no perl or pipes required. That is the whole pitch, and it is a real one. You run one command, and you get an SVG.

The audience is broader than Rust developers, even though the cargo integration is the most visible part. The standalone flamegraph binary takes an arbitrary executable as a trailing argument, so a C, C++ or Go binary works the same way. The Rust part is the packaging: cargo install flamegraph puts both flamegraph and cargo-flamegraph in your cargo binary directory, typically ~/.cargo/bin, and the second binary is what makes cargo flamegraph resolve.

Where the project is opinionated is in what it does not do. It does not sample by itself on Linux; it drives perf. It does not present an interactive UI. It writes a file, and on most systems it opens that file in your browser through the opener crate. If you want to click around, hold state, or diff two runs, this is not the tool.

## The sampling backends and where the data comes from

flamegraph is a front end. The README states that Linux relies on perf, macOS relies on xctrace, and Windows has native support through the blondie library, with dtrace as an alternative on Windows. On Windows, if dtrace is found, flamegraph always prefers it over the built-in backend. That preference is worth knowing because the two produce different stack quality, and you cannot tell from the command line which one ran.

The output side is Inferno, described in the README as an all-Rust flamegraph generation library. Cargo.toml confirms the dependency with inferno = { version = "0.12.2", default-features = false, features = ["multithreaded", "nameattr"] }. The multithreaded feature matters for large profiles, and nameattr is what lets function names carry attributes in the SVG.

The flow is therefore: flamegraph builds or attaches to a process, invokes the platform sampler, captures stacks, demangles them with rustc-demangle, and hands the folded data to Inferno, which writes the SVG. That is four moving parts, and each one can fail independently. A missing perf binary, a stripped binary without frame pointers, or a linker that hides the return address all produce an SVG. It just will not be an SVG that tells you anything.

## Installing flamegraph and producing a first SVG

Installation is one cargo command. It places two binaries in your cargo binary directory, which the README says is usually ~/.cargo/bin.

```bash
cargo install flamegraph
```

On Linux you also need perf, which is packaged separately from the Rust toolchain. On Debian the README gives this:

```bash
sudo apt install -y linux-perf
```

On Ubuntu the package set is different, and the kernel version is part of the package name:

```bash
sudo apt install linux-tools-common linux-tools-generic linux-tools-`uname -r`
```

Once that is in place, profiling a Rust project is a single command from the project directory. The README notes that this defaults to profiling cargo run --release.

```bash
cargo flamegraph
```

For a binary that is not a Cargo project, or one you have already built, the standalone binary takes the path after a double dash. Arguments after the path are passed through to the program being profiled.

```bash
flamegraph -o my_flamegraph.svg -- /path/to/my/binary --my-arg 5
```

If the process is already running, the README gives -p or --pid, for example flamegraph --pid 1337. Expect an SVG in the current directory, and on most systems a browser tab opening it.

## The linker flag that decides whether your Linux profile means anything

This is the part of the README most likely to be skimmed and most likely to cost you an afternoon. The README states that if you use lld, which it says is the default since Rust 1.90.0, or mold on Linux, you must pass --no-rosegment, otherwise perf will not be able to generate accurate stack traces. The README links to a Chromium bug for the explanation. The Cargo.toml in the repository sets rust-version = "1.88", so a project on a current toolchain is right in the affected range.

The fix goes in .cargo/config.toml. For Rust 1.90.0 and later the README gives:

```toml
[target.x86_64-unknown-linux-gnu]
rustflags = ["-Clink-arg=-Wl,--no-rosegment"]
```

There are separate snippets for explicitly configured lld on older toolchains and for mold, both of which add the flag alongside their own linker arguments. The detail that matters is that this is a build-time change. It is not a flamegraph flag, it does not show up in the flamegraph help output, and nothing in the generated SVG will warn you that you forgot it. You get stacks that look shallow or attribute time to the wrong frames.

A related trap on Ubuntu is that perf is not packaged for every kernel. The README walks through checking /usr/lib/linux-tools/`uname -r`/ for the binary, and if it is missing, symlinking perf from another installed kernel version into place. That workaround is documented, which means people hit it often enough to write it down.

## Inlining, --no-inline, and the cost of accurate frames

By default, the README says perf tries to compute which functions are inlined at every stack frame for every sample, and that this can take a very long time. The project links issue 74 for the details. The escape hatch is --no-inline.

This is a genuine trade-off with no free side. Inlined frames are often exactly where the interesting work is: a small function that the optimizer folded into its caller will not appear in the profile unless perf does that resolution. Turning it off makes the run finish sooner and makes the resulting graph coarser. For a quick orientation pass on a large program, --no-inline is the right call. For deciding whether a specific hot path is worth rewriting, it can hide the function you were looking for.

The same tension shows up in the -c passthrough. The README gives cargo flamegraph -c "record -e branch-misses -c 100 --call-graph lbr -g" as a way to reach perf or dtrace options directly, and mentions branch-misses and cache-misses as examples. That flag is powerful and it is also a hole in the abstraction: once you are writing perf record arguments, flamegraph is a convenience wrapper and you are responsible for knowing what the sampler is doing.

## What flamegraph does not do: diffing, live views and macOS depth

There is no diff mode. The related searches people run include flamegraph diff, and the README does not document one. If your question is whether this change made things faster, a single SVG answers it only by eye, and the README offers nothing better. You would be comparing two images.

There is no interactive view either. The README's own tip points readers at samply, described there as providing a more interactive UI with integration into Firefox's Profiler web UI, written in Rust, with better macOS support. That is the project telling you where its own boundary is. samply streams into a profiler UI where you can search and select; flamegraph writes a static document.

macOS is the weaker platform, by the project's own admission in that tip. The backend is xctrace, and the Cargo.toml carries a macOS-specific dependency on quick-xml, which suggests parsing xctrace's XML output rather than a direct sampling API. The README does not document the fidelity of that path, so treat macOS results as a rougher signal than Linux perf results.

One more boundary: cargo-flamegraph has no shell completion. The README states that only flamegraph supports auto-completion, for bash, fish, zsh, powershell and elvish, and that cargo-flamegraph does not because it is not straightforward for custom cargo subcommands, linking pull request 153. Completion for the standalone binary is enabled with a redirect, for example flamegraph --completions bash > $XDG_CONFIG_HOME/bash_completion.

## Licence and the cost of keeping it current

Cargo.toml declares license = "MIT OR Apache-2.0", and the repository root carries LICENSE-APACHE and LICENSE-MIT. The dual licence is the Rust ecosystem default and is permissive; the practical consequence for most teams is attribution and retention of the licence text, not a constraint on shipping the binary. This is a description of the declared terms, not legal advice, and the MIT OR form means you choose one of the two.

Upgrade cost is low and mostly external. The crate itself has no service component and no configuration file to migrate, so cargo install flamegraph is the whole upgrade path. The maintenance you should budget for is in the environment: perf packaging changes with kernel versions, and the README already documents a symlink workaround for Ubuntu kernels without a matching perf package. The last push to the repository was on 2026-09-01, and the most recent release listed is v0.6.14 on 2026-08-12.

The dependency that ages least gracefully is the platform sampler. Inferno is pinned to a 0.x version, and the Windows path depends on blondie 0.5.2 or on a dtrace installation you manage yourself. None of these are reasons to avoid the tool, but they explain why the release cadence matters more here than for a pure library.

## Conclusion

Adopt flamegraph if you want a single SVG per run with no Perl and no pipeline to assemble, and if you are willing to accept a snapshot rather than a live view. Do not adopt it if you need to compare two profiles or interact with the data; the README itself points at samply for a more interactive UI. Before you trust a Linux profile, verify that your linker flags include --no-rosegment and that perf actually resolves your symbols, because a flamegraph built from broken stacks looks plausible and is worthless.

## FAQ

### How do I install flamegraph and cargo flamegraph?

Run cargo install flamegraph. The README states this makes both the flamegraph and cargo-flamegraph binaries available in your cargo binary directory, which is usually ~/.cargo/bin. On Linux you also need perf installed separately, for example linux-perf on Debian.

### How do I use cargo flamegraph on a Rust project?

From the project directory, run cargo flamegraph. The README says it defaults to profiling cargo run --release, and that you can switch with --dev or --profile, or pick a target with --bin.

### How do I generate a flame graph for a binary that is not a Cargo project?

Use the standalone binary and pass the path after a double dash, as in flamegraph -- /path/to/binary. The README also shows -o for the output file and --pid for an already running process.

### Why are my Linux stack traces inaccurate with flamegraph?

The README states that if you use lld (the default since Rust 1.90.0) or mold on Linux, you must pass --no-rosegment through rustflags, otherwise perf cannot generate accurate stack traces. The flag goes in .cargo/config.toml, not on the flamegraph command line.

### What is the difference between a flame graph and a flame chart?

The README does not discuss flame charts or draw that distinction. It describes the SVG output as a flamegraph generated by Inferno from sampled stacks, and links to its own explanation of how to read one for systems performance work.

## Sources

- [flamegraph-rs/flamegraph on GitHub](https://github.com/flamegraph-rs/flamegraph)
- [Issues](https://github.com/flamegraph-rs/flamegraph/issues)
- [License: Apache-2.0](https://github.com/flamegraph-rs/flamegraph/blob/main/LICENSE)
- [README](https://github.com/flamegraph-rs/flamegraph/blob/main/README.md)
- [Releases](https://github.com/flamegraph-rs/flamegraph/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/flamegraph-rs-flamegraph
