Cargo can build and execute Rust benchmark targets from the same package manifest that drives builds and tests. Running benchmarks before a performance-sensitive change or release gives the crate an optimized timing pass instead of relying on debug builds or ordinary unit tests.
Benchmark targets usually live under benches, and Cargo builds them with the bench profile. The built-in #[bench] attribute is nightly-only, so stable projects commonly use a custom harness or a benchmarking crate such as Criterion while keeping cargo bench as the entry command.
A small custom harness with harness = false can run on stable Rust without external dependencies. Existing projects that already have benchmark targets can skip the file setup and run cargo bench from the package root.
Related: How to run Rust tests with Cargo
Related: How to create a Rust project with Cargo
Use cargo bench --manifest-path path/to/Cargo.toml when launching Cargo from another directory.
$ mkdir -p benches
use std::{hint::black_box, time::Instant}; fn main() { let input = "simplified-guide-benchmark"; let rounds = 1_000_000; let started = Instant::now(); let mut total = 0; for _ in 0..rounds { total += black_box(input).len(); } black_box(total); println!( "string_len: {rounds} iterations in {:?} (total={total})", started.elapsed() ); }
std::hint::black_box keeps the optimizer from removing the measured loop in the minimal benchmark.
[[bench]] name = "string_len" harness = false
harness = false disables the default libtest benchmark harness, so the benchmark file provides its own main function.
$ cargo bench --no-run --bench string_len
Compiling demo-lib v0.1.0 (/home/dev/demo-lib)
Finished `bench` profile [optimized] target(s) in 1.09s
Executable benches/string_len.rs (target/release/deps/string_len-2ce2528f213845aa)
Use --no-run when compile errors should be caught before collecting timing output.
$ cargo bench --bench string_len
Finished `bench` profile [optimized] target(s) in 0.01s
Running benches/string_len.rs (target/release/deps/string_len-2ce2528f213845aa)
string_len: 1000000 iterations in 581.792µs (total=26000000)
A custom main function controls this output line. A Criterion benchmark or nightly #[bench] target reports in its own harness format.
$ cargo bench
Compiling demo-lib v0.1.0 (/home/dev/demo-lib)
Finished `bench` profile [optimized] target(s) in 0.27s
Running unittests src/lib.rs (target/release/deps/demo_lib-3c68178e29f1f907)
running 1 test
test tests::it_works ... ignored
test result: ok. 0 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 0.00s
Running benches/string_len.rs (target/release/deps/string_len-2ce2528f213845aa)
string_len: 1000000 iterations in 398.625µs (total=26000000)
Options before -- belong to Cargo. Arguments after -- are passed to the benchmark binary or harness.