Benchmarking
====================

[![CI](https://github.com/magiclen/benchmarking/actions/workflows/ci.yml/badge.svg)](https://github.com/magiclen/benchmarking/actions/workflows/ci.yml)

This crate can be used to execute something and measure the execution time. It does not output anything to screens and filesystems.

## Examples

```rust
const VEC_LENGTH: usize = 100;

benchmarking::warm_up();

let bench_result = benchmarking::measure_function(|measurer| {
    let mut vec: Vec<usize> = Vec::with_capacity(VEC_LENGTH);

    unsafe {
        vec.set_len(VEC_LENGTH);
    }

    for i in 0..VEC_LENGTH {
        measurer.measure(|| {
            vec[i]
        });
    }

    vec
}).unwrap();

println!("Reading a number from a vec takes {:?}!", bench_result.elapsed());
```

```rust
const VEC_LENGTH: usize = 100;

benchmarking::warm_up();

let bench_result = benchmarking::measure_function(|measurer| {
    let mut vec: Vec<usize> = Vec::with_capacity(VEC_LENGTH);

    measurer.measure(|| {
        for i in 0..VEC_LENGTH {
            vec.push(i);
        }
    });

    vec
}).unwrap();

println!("Filling 0 to 99 into a vec takes {:?}!", bench_result.elapsed());
```

```rust
const VEC_LENGTH: usize = 100;

benchmarking::warm_up();

let bench_result = benchmarking::measure_function(|measurer| {
    let mut vec: Vec<usize> = Vec::with_capacity(VEC_LENGTH);

    for loop_seq in 0..VEC_LENGTH {
        measurer.measure(|| {
            vec.push(loop_seq);
        });
    }

    vec
}).unwrap();

println!("Pushing a number into a vec takes {:?}!", bench_result.elapsed());
```

```rust
const VEC_LENGTH: usize = 100;

benchmarking::warm_up();

let bench_result = benchmarking::measure_function_n(2, |measurers| {
    let mut vec: Vec<usize> = Vec::with_capacity(VEC_LENGTH);

    for i in 0..VEC_LENGTH {
        measurers[1].measure(|| {
            vec.push(i);
        });
    }

    for i in 0..VEC_LENGTH {
        measurers[0].measure(|| {
            vec[i]
        });
    }

    vec
}).unwrap();

println!("Reading a number from a vec takes {:?}!", bench_result[0].elapsed());
println!("Pushing a number into a vec takes {:?}!", bench_result[1].elapsed());
```

* The `warm_up` and `warm_up_with_duration` functions of the `benchmarking` crate run on one thread. To warm up all CPUs, you can use the `warm_up_multi_thread` and `warm_up_multi_thread_with_duration` functions instead.
* The `measure_function` and `measure_function_with_times` functions of the `benchmarking` crate can execute a closure for N times. The `times` argument of the `_with_times` functions must be greater than `0`, and this condition is checked by `debug_assert!` in debug builds. To execute it repeatedly for a while instead, you can use the `bench_function` and `bench_function_with_duration` functions.
* To execute a closure with multiple threads to measure the throughput, you can use the `multi_thread_bench_function`, `multi_thread_bench_function_with_duration`, `multi_thread_bench_function_n`, and `multi_thread_bench_function_n_with_duration` functions of the `benchmarking` crate. These functions aggregate measured operation counts across all threads and average elapsed time by thread count, so `MeasureResult::speed` represents approximate total throughput, not per-thread latency.

## Crates.io

https://crates.io/crates/benchmarking

## Documentation

https://docs.rs/benchmarking

## License

[MIT](LICENSE)