4

I have a binary project with a lot of internal modules to organise functionality.

I'm trying to get Criterion working for benchmarks.

The error:

error[E0432]: unresolved import `crate::some_module`
 --> benches/benchmarks.rs:3:5
  |
3 | use crate::some_module;
  |     ^^^^^^^^^^^^^^^^^^ no `some_module` in the root

error: aborting due to previous error

Minimal example .zip: https://drive.google.com/file/d/1TASKI9_ODJniamHp3RBRscoflabPT-kP/view?usp=sharing

My current minimal example looks like:

.
├── Cargo.lock
├── Cargo.toml
├── src/
│   ├── main.rs
│   └── some_module/
│       ├── mod.rs
│       └── some_module_file.rs
└── benches/
    └── benchmarks.rs

Cargo.toml:

[package]
name = "criterion-bin-test"
version = "0.1.0"
authors = ["Jonathan <jonthanwoollettlight@gmail.com>"]
edition = "2018"

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

[dependencies]

[dev-dependencies]
criterion = "0.3"

[[bench]]
name = "benchmarks"
harness = false

main.rs:

mod some_module;

fn main() {
    println!("Hello, world!");

    println!("{}",some_module::some_mod_file::two());
}

mod.rs:

pub mod some_mod_file;

some_module_file:

pub fn two() -> i32 {
    2
}

benchmarks.rs:

use criterion::{black_box, criterion_group, criterion_main, Criterion};

use crate::some_module;

fn fibonacci(n: u64) -> u64 {
    match n {
        0 => 1,
        1 => 1,
        n => fibonacci(n-1) + fibonacci(n-2),
    }
}

fn criterion_benchmark(c: &mut Criterion) {
    c.bench_function("fib 20", |b| b.iter(|| fibonacci(black_box(20))));
}

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

The error arises on use crate::some_module, and I cannot figure out how to apply Criterion benchmarks to internal module.

Tests in my current project are handled as:

.
├── Cargo.lock
├── Cargo.toml
├── src/
|   ├── main.rs
.   ├── tests.rs
    . some_module/
        ├── mod.rs
        ├── tests.rs
        .

Which allows for use crate::some_module.

halfer
  • 19,824
  • 17
  • 99
  • 186
Jonathan Woollett-light
  • 2,813
  • 5
  • 30
  • 58
  • As with tests placed in the `/tests` directory, benchmarks placed in the `/benches` directory only have access to your crate’s *public* API; since your crate does not provide a library target in addition to the binary, it does not currently have any public API. Either move `some_module` into a library target (that is linked to both the binary target and the benchmarks) or else move these benchmarks into the `/src` folder so that they can use the binary’s *private* API (just like the tests you currently have in the `/src` folder). – eggyal Jun 28 '21 at 05:57
  • 1
    Okay, so moving `benchmarks.rs` into `src/` produces the error `can't find 'benchmarks' bench, specify bench.path` which I think relates to setting of `[[bench]] \n name = "benchmarks" \n harness = false` in `Cargo.toml`, not sure how to proceed after this? – Jonathan Woollett-light Jun 28 '21 at 06:09
  • Well, if you go that route of moving the benchmarks into your binary, then you no longer have a separate benchmark target to build (and so should remove that target from your `Cargo.toml`). I’m not familiar enough with Criterion to say whether it supports embedded benchmarks like this, however—probably not. I guess you’re better to go the other route, of moving `some_module` into a library target in order that you can then stick with an isolated benchmark target as per the Criterion documentation. – eggyal Jun 28 '21 at 06:15
  • How would I move `some_module` into a library target? – Jonathan Woollett-light Jun 28 '21 at 06:22
  • 1
    Easiest thing would be to move `main.rs` into `/src/bin` changing `mod some_module;` to `use criterion_bin_test::some_module;` and then create `/src/lib.rs` containing `pub mod some_module;`. – eggyal Jun 28 '21 at 06:27
  • See https://stackoverflow.com/q/26946646 – eggyal Jun 28 '21 at 06:28

1 Answers1

3

for anyone struggling with this issue.

When implementing benchmarks (or examples), if we want to include some of our modules/functions, we have to do it the same way we would if we were including those from our already installed package.

For instance, in the question above there is an error indicating that:

error[E0432]: unresolved import `crate::some_module`
 --> benches/benchmarks.rs:3:5
  |
3 | use crate::some_module;
  |     ^^^^^^^^^^^^^^^^^^ no `some_module` in the root

error: aborting due to previous error

That's because it should read like:

use criterion-bin-test::some_module;

Where criterion-bin-test is the actual package name, use that instead of crate:: when implementing examples or benchmarks;

Raydel Miranda
  • 13,825
  • 3
  • 38
  • 60