Rust Criterion benchmark not working – Optimized out

117 Views Asked by At

I'm running these benchmarks, they use a function which is a loop that counts to 10M and 100M:

use crab::count_up_to;
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use rand::Rng;

pub fn criterion_benchmark(c: &mut Criterion) {
    c.bench_function("10M", |b| {
        b.iter(|| {
            let num = rand::thread_rng().gen_range(0..100);
            let r = count_up_to(black_box(10_000_000 + num));
            eprintln!("{}", r);
        });
    });

    c.bench_function("100M", |b| {
        b.iter(|| {
            let r = count_up_to(100_000_000);
            eprintln!("{}", black_box(r));
        });
    });

    c.bench_function("hello", |b| {
        b.iter(|| {
            eprintln!("{}", "hello");
        });
    });
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);

I've added a third benchmark that only outputs to stderr for reference. The problem as you may guess is that all 3 benchmarks take the same time, less than 1µs, which clearly mean the count_up_to function is being optimized out.

I wonder why that is since I end up using the result of the function and as you may note in the first test (the 10M) the parameters are not always the same since a little random noise is added. I've also tried to use black_box in different places with no luck.

Any help is greatly appreciated.

Here's Cargo.toml and the implementation of count_up_to:

[package]
name = "crab"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

[dev-dependencies]
criterion = { version = "0.4", features = ["html_reports"] }
rand = "0.8"

[[bench]]
name = "count"
harness = false
pub fn count_up_to(n: usize) -> usize {
    let mut count = 0;
    while count < n {
        count += 1;
    }
    count / 2 * 100
}
1

There are 1 best solutions below

2
Chayim Friedman On

The compiler just realizes the loop is equal to let count = n: https://rust.godbolt.org/z/Mo1hGa5Pa. You can add black_box(): count += std::hint::black_box(1);.

Also, printing in iter() is a very bad idea, it'll take up all of the time. And you'll need to black_box() the 100_000_000 parameter too.