• Rust代码基准测试框架Divan的使用
  • 发布于 2个月前
  • 187 热度
    0 评论
Divan是一个快速舒适的Rust代码基准测试框架,让我们通过例子来学习它。

新建一个Rust项目:
cargo new divan-example
Cargo.toml文件的内容如下:
[dev-dependencies]
divan = "0.1.2"

[[bench]]
name = "example"
harness = false
在项目根目录下创建benches目录,在目录下创建一个example.rs文件,文件代码如下:
fn main() {
    // 运行已注册的基准测试
    divan::main();
}

// 定义一个' fibonacci '函数并将其注册为基准测试
#[divan::bench]
fn fibonacci() -> u64 {
    fn compute(n: u64) -> u64 {
        if n <= 1 {
            1
        } else {
            compute(n - 2) + compute(n - 1)
        }
    }

    compute(divan::black_box(10))
}
使用#[Divan::bench]属性可以在任何地方注册Divan基准测试,类似于#[test]。

运行cargo bench命令进行测试,结果如下:
Timer precision: 15 ns
example       fastest       │ slowest       │ median        │ mean          │ samples │ iters
╰─ fibonacci  191.5 ns      │ 204.8 ns      │ 192.4 ns      │ 193.2 ns      │ 100     │ 800
属性选项
每个基准测试还可以通过属性选项来控制,比如max_time和sample_size:
#[divan::bench(
    max_time = 0.001, // 秒
    sample_size = 64, // 64 × 80 = 5120
)]
fn fibonacci() -> u64 {
    ......
}
测试结果如下:
Timer precision: 15 ns
example       fastest       │ slowest       │ median        │ mean          │ samples │ iters
╰─ fibonacci  189.9 ns      │ 196.7 ns      │ 190 ns        │ 190.1 ns      │ 80      │ 5120
模块树结构
如果我们想比较fibonacci的递归实现和迭代实现,可以把它们放在一个模块中:
mod fibonacci {
    const N: u64 = 10;

    // 迭代实现
    #[divan::bench]
    fn iterative() -> u64 {
        let mut previous = 1;
        let mut current = 1;

        for _ in 2..=divan::black_box(N) {
            let next = previous + current;
            previous = current;
            current = next;
        }

        current
    }

    // 递归实现
    #[divan::bench]
    fn recursive() -> u64 {
        fn compute(n: u64) -> u64 {
            if n <= 1 {
                1
            } else {
                compute(n - 2) + compute(n - 1)
            }
        }

        compute(divan::black_box(N))
    }
}
测试结果如下:
Timer precision: 14 ns
example          fastest       │ slowest       │ median        │ mean          │ samples │ iters
╰─ fibonacci                   │               │               │               │         │
   ├─ iterative  9.152 ns      │ 15.12 ns      │ 9.187 ns      │ 9.535 ns      │ 100     │ 25600
   ╰─ recursive  191.5 ns      │ 285.8 ns      │ 192.3 ns      │ 202.3 ns      │ 100     │ 800
fibonacci迭代实现明显比递归实现的效率高很多。

泛型测试
Divan可以对泛型函数进行基准测试,下面的基准测试示例用于测试From<&str>转换为&str和String的性能:
#[divan::bench(types = [
    &str,
    String,
])]
fn from_str<'a, T>() -> T
where
    T: From<&'a str>,
{
    divan::black_box("hello world").into()
}
测试结果如下:
Timer precision: 19 ns
example       fastest       │ slowest       │ median        │ mean          │ samples │ iters
╰─ from_str                 │               │               │               │         │
   ├─ &str    1.809 ns      │ 3.289 ns      │ 1.819 ns      │ 1.902 ns      │ 100     │ 102400
   ╰─ String  80.12 ns      │ 127.5 ns      │ 81.02 ns      │ 82.75 ns      │ 100     │ 3200
从测试结果可以看出,From<&str>转换为String的性能更低,因为涉及到堆分配操作。
用户评论