cargo-instruments: profiling a Rust binary with Xcode Instruments
A cargo plugin to generate Xcode Instruments trace files
At a glance
- What is it?
- cargo-instruments is a Cargo plugin that runs your binary under Xcode's bundled Instruments profiler and writes a .trace file you can open in the Instruments app. It is macOS only, and the README is precise about the one prerequisite that trips people up, which is the full Xcode rather than the command line tools.
- Who is it for?
- cargo-instruments is the right tool for a Rust developer on macOS who wants the Instruments app rather than a Linux profiler, because it removes the whole invocation dance and gives you the same trace format and templates that Apple ships, including allocations, leaks and the system trace. It is the wrong choice on Linux or Windows, since the plugin shells out to Instruments, and the wrong choice when you want a profiler that works in continuous integration.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The glue between Cargo and Instruments
cargo-instruments describes itself as the glue between Cargo and Xcode's bundled profiling suite, and the practical description is that it lets you profile any binary in your crate, generating files that can be viewed in the Instruments app.
The gap it fills is real. Instruments is a good profiler with good templates and a good interface for exploring a trace, but driving it against a Cargo project means handling the build, finding the binary, launching the profiler with the right template, and then opening the resulting trace. This plugin does that as a Cargo subcommand.
The scope is narrow on purpose. It requires a binary target to run, and by default it builds the current crate's main.rs. You can point it at a different binary with the bin or example flags, or at a benchmark target with the bench flag. In a workspace with several packages, the package flag selects which one, and the README notes the common simplification that when a package has only one binary the package flag behaves the same as the bin flag.
The plugin is written in Rust, published on crates.io as cargo-instruments, MIT licensed, and the README links screenshots of the Time Profiler and the System Trace views so you can see what the output looks like before installing anything.
The prerequisite that catches people out
The pre-requisites section is short and has one warning that matters more than the rest.
The crate only works on macOS, because it uses Instruments for profiling and for creating the trace file. The benefit of that dependency is stated plainly: Instruments provides good templates and a good interface for exploring the profiling trace.
The warning is about which Xcode you have. To install Instruments you need Xcode from the App Store, and the README is explicit that the Command Line Tools you might already have installed while setting up Rust are not sufficient.
That is the single most common failure for this plugin, because a Rust developer on macOS often has the command line tools from the Rust installer and nothing else. The verification step is to run the xctrace tool, which should print help output if the full Xcode is present.
If you see an error about the active developer directory, the README points at the xcode-select path command.
$ xcode-select --print-path
/Applications/Xcode.app/Contents/DeveloperAnd the fix is the reset command, which needs administrator rights.
$ sudo xcode-select --resetInstalling it, including the OpenSSL and Nix paths
The simplest installation is Homebrew.
$ brew install cargo-instrumentsBuilding from source needs macOS with Cargo, Xcode and the Xcode Command Line Tools installed. If OpenSSL is present, for example through brew, the ordinary install command works.
$ cargo install cargo-instrumentsIf OpenSSL is missing, or if the install fails with an error about not finding the OpenSSL installation directory, the README gives the feature flag that solves it.
$ cargo install --features vendored-openssl cargo-instrumentsThat vendored-openssl feature is visible in the Cargo manifest as a single line that forwards to the same feature on the cargo dependency, so it builds its own OpenSSL rather than linking the system one. It is the difference between the install working on a clean machine and not.
For Nix users there is a longer command that provides the full dependency set, including the Apple SDK frameworks for SystemConfiguration and CoreServices, the Rust toolchain, sccache, libgit2, pkg-config, libiconv, a libclang from the LLVM packages and openssl. The nix-shell invocation is run with a pure environment so that nothing leaks into the surrounding shell.
That is a fair amount of machinery for a profiler, and it is a reminder that this is a macOS only tool with a macOS only toolchain.
The basic profiling run
The typical run names a template and lets the plugin do the rest.
$ cargo instruments -t AllocationsThe trace file is written by default into the target/instruments directory, with a name that combines the binary and the template, and the trace is opened in Instruments.app immediately afterwards. If you would rather not have that happen, for example in a script, the no-open flag suppresses it, and the file can be opened manually later.
$ open target/instruments/mybin_Allocations_2021-05-09T12_34_56.traceIn a workspace the package and binary are selected together, and the template can be given by its abbreviation.
$ cargo instruments --package foo --template alloc --bin barThe flag surface is wider than that, and the README prints the compact help, generated with Clap, so the options are readable without leaving the terminal. Beyond the target selection there is the release flag to pass through to Cargo, the profile flag for a custom profile, the features flags for feature selection, the manifest path, an output path for the trace file, and a time limit in milliseconds that caps how long the recording runs.
Two of those deserve attention. The time limit is the difference between an interactive profile and a bounded one that you can run without watching. And the no-demangle flag exists because Rust symbol names in the trace are demangled by default, and there is a case for turning that off.
Debug symbols and the release profile
There is one configuration detail that will ruin your first profiling run if you miss it, and the README gives the fix in a config snippet.
When profiling the application in release mode, the compiler does not provide debugging symbols in the default configuration. To let the compiler generate them even in a release build, you add a profile section to your Cargo.toml.
[profile.release]
debug = trueThat is the standard Cargo mechanism, and it is worth understanding why it matters here specifically. A profile without symbols gives you a trace full of addresses, and the difference between a trace you can read and one you cannot is exactly this flag.
The symbol handling is not incidental to the project either. The Cargo manifest pulls in the object crate with the read_core and macho features and no default features, plus the rustc-demangle crate, and the dependencies include the cargo crate and clap. Reading the Mach-O file of the built binary is how the plugin gets the symbol table it needs to demangle Rust names in the profiling output.
That is a design choice with a consequence: the plugin is not a wrapper around a shell command, it parses the binary it is about to profile.
Templates, the Instruments vocabulary
Instruments has the concept of templates, which describe sets of dtrace probes that can be enabled. The plugin can list the available templates, including your own custom ones, and if you do not give a template name it prompts you to choose one.
The built-in list is long and it tells you what the profiler is actually useful for: Activity Monitor, Allocations with the abbreviation alloc, Animation Hitches, App Launch, Audio System Trace, CPU Counters, the CPU Profiler with the abbreviation cpu, Core ML, Data Persistence, File Activity with io, Game Memory, Game Performance and its Overview variant, Leaks, Logging, Metal System Trace, Network, Power Profiler, Processor Trace, RealityKit Trace, Swift Concurrency, SwiftUI, the System Trace with sys, Tailspin and Time Profile.
Three of those are worth calling out for a Rust developer. Allocations and Leaks are how you find memory growth, File Activity is how you find a program doing something silly with the filesystem, and the System Trace is the wide view of scheduling, IO and GPU work.
The abbreviations matter in practice because typing the full template name on the command line is tedious, and the plugin's own help shows the short form in use, with the Time Profiler example given as the recommended one.
Compatibility, versions and where this does not work
The crate works on macOS 10.13 and later, and it handles the change of Instruments command line across that span transparently: on older systems it uses the instruments binary in /usr/bin, and from macOS 10.15 it uses the new xcrun xctrace. You do not have to pick the right one yourself.
The version picture is modest but honest. The release tags are 0.4.16 from 2026-05-13, 0.4.10 from 2024-06-20 and 0.4.9 from 2023-11-13, and the last push was recent. The Cargo manifest in the repository is at version 0.4.17, so the branch is slightly ahead of the last tag, and it targets Rust edition 2024 with the cargo crate at 0.97.
The boundary is worth stating plainly. This is a macOS only plugin that shells out to a macOS only profiler, so it does nothing for a team that develops on Linux and profiles in CI, where you would use a Linux native profiler instead. It is also a development tool rather than a library, so the cost of adopting it is a dependency on your machine rather than on your build.
For a Rust developer on a Mac with the full Xcode installed, the remaining question is which template answers the question you are asking, and the plugin makes that a one flag change.
Editorial conclusion
cargo-instruments is the right tool for a Rust developer on macOS who wants the Instruments app rather than a Linux profiler, because it removes the whole invocation dance and gives you the same trace format and templates that Apple ships, including allocations, leaks and the system trace. It is the wrong choice on Linux or Windows, since the plugin shells out to Instruments, and the wrong choice when you want a profiler that works in continuous integration. Verify first that the full Xcode is installed rather than only the command line tools, that the binary you are profiling is built with debug symbols, which release profiles do not provide by default, and that the template you need exists in the list the plugin prints, since custom templates are part of the Instruments installation rather than the plugin.
Frequently asked questions
What does cargo-instruments do?
It is a Cargo plugin that profiles a binary target of your crate using Xcode Instruments and produces a .trace file that can be opened in the Instruments app.
Do I need the full Xcode to use cargo-instruments?
Yes. The README says the crate only works on macOS because it uses Instruments, and that the Command Line Tools you may have installed while setting up Rust are not sufficient. You can verify the installation by running xctrace and checking that it prints help.
How do I install cargo-instruments without a system OpenSSL?
Install it with the vendored-openssl feature, for example cargo install --features vendored-openssl cargo-instruments, which the README recommends when OpenSSL is missing or the install fails with an error about not finding the OpenSSL installation directory.
Why does my release profile trace show no symbols?
Because the compiler does not provide debugging symbols in the default release configuration. The README recommends adding a profile.release section with debug set to true in your Cargo.toml.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/cmyr-cargo-instruments)Was this useful?