Criterion for Rust: Complete Guide with Examples

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

What is Criterion and why is it needed?

\n\n

Criterion.rs is a powerful and flexible library for benchmarking (performance testing) in the Rust language. It is a direct analogue of the popular Criterion library for Haskell, but adapted for the Rust ecosystem.

\n\n

Why is Criterion needed? Unlike simple time measurements using std::time::Instant, Criterion provides:

\n
    \n
  • Statistical analysis: Automatically runs the code many times, collects a sample of execution times, and calculates the mean, median, standard deviation, and percentiles.
  • \n
  • Comparison with baseline: Allows comparing the performance of the current code version with a previous one (regression testing).
  • \n
  • Report generation: Creates beautiful HTML reports with charts and tables.
  • \n
  • Parametric benchmarking: Easily test the performance of a function with different input data.
  • \n
  • Noise resistance: Criterion's algorithms are resistant to execution time fluctuations caused by background OS processes.
  • \n
\n\n

The library is indispensable for developers who want to:

\n
    \n
  • Optimize critical code sections.
  • \n
  • Ensure that new code does not slow down existing functionality.
  • \n
  • Make decisions based on data, not guesses.
  • \n
\n\n

Installing Criterion in a Rust Project

\n\n

Unlike Python (pip) or Node.js (npm), in Rust libraries are installed via the Cargo package manager. Criterion is not a library for main code, but a testing tool, so it is added to the [dev-dependencies] section of the Cargo.toml file.

\n\n

You will also need to create a benches/ directory in the root of your project (next to src/).

\n\n

Step 1: Add the dependency to Cargo.toml

\n
[dev-dependencies]\ncriterion = { version = "0.5", features = ["html_reports"] }
\n

Note: The features = ["html_reports"] flag enables HTML report generation. Without it, only text output to the console will be available.

\n\n

Step 2: Create a benchmark file

\n

Create a file benches/my_benchmark.rs (the name can be anything).

\n\n

Step 3: Run the benchmark

\n
cargo bench
\n

This command will compile your project in release mode (with optimizations) and run all benchmarks from the benches/ folder.

\n\n

Quick Start: First Benchmark

\n\n

Let's write a simple benchmark that measures the speed of summing numbers from 0 to 99.

\n\n
// benches/my_benchmark.rs\nuse criterion::{black_box, criterion_group, criterion_main, Criterion};\n\n// Function we will test\nfn sum_slow(n: u64) -> u64 {\n    let mut sum = 0;\n    for i in 0..n {\n        sum += i;\n    }\n    sum\n}\n\nfn sum_fast(n: u64) -> u64 {\n    n * (n - 1) / 2\n}\n\nfn criterion_benchmark(c: &mut Criterion) {\n    // Group benchmarks\n    let mut group = c.benchmark_group("sum_comparison");\n    \n    group.bench_function("slow", |b| b.iter(|| sum_slow(black_box(100))));\n    group.bench_function("fast", |b| b.iter(|| sum_fast(black_box(100))));\n    \n    group.finish();\n}\n\n// Macros for registration and launch\ncriterion_group!(benches, criterion_benchmark);\ncriterion_main!(benches);
\n\n

What is happening here?

\n
    \n
  • black_box() — tells the compiler that the value should be passed "as is", preventing premature optimization (the compiler might compute the constant at compile time, which would distort the result).
  • \n
  • b.iter() — the main benchmark loop. Criterion will call this closure many times and measure the time.
  • \n
  • <

Recommendations