Skip to main content

fast_des/
benchmark.rs

1use std::{
2    sync::{Arc, Barrier},
3    thread,
4    time::{Duration, Instant},
5};
6
7struct BenchmarkResult {
8    runs: u64,
9    duration: Duration,
10}
11
12pub fn benchmark<F>(name: &str, runs: u64, warmup: u64, parallel_count: u64, mut func: F)
13where
14    F: FnMut(),
15{
16    for _ in 0..warmup {
17        std::hint::black_box(func());
18    }
19    let start = Instant::now();
20    for _ in 0..runs {
21        std::hint::black_box(func());
22    }
23    let duration = start.elapsed();
24    let result = BenchmarkResult { runs, duration };
25    let hashes_per_second =
26        (result.runs as f64 / result.duration.as_secs_f64()) * parallel_count as f64;
27    print_report(name, hashes_per_second);
28}
29
30pub fn benchmark_parallel<F>(
31    name: &str,
32    runs: u64,
33    parallel_count: u64,
34    thread_count: usize,
35    mut func: F,
36) where
37    F: FnMut() + Send + Clone + 'static,
38{
39    let barrier = Arc::new(Barrier::new(thread_count));
40    let mut handles = Vec::with_capacity(thread_count);
41
42    let start_time = Instant::now();
43
44    for _ in 0..thread_count {
45        let mut func_clone = func.clone();
46        let c_barrier = Arc::clone(&barrier);
47
48        handles.push(thread::spawn(move || {
49            c_barrier.wait();
50
51            for _ in 0..runs {
52                func_clone();
53            }
54        }));
55    }
56
57    for handle in handles {
58        handle.join().unwrap();
59    }
60
61    let duration = start_time.elapsed();
62
63    let result = BenchmarkResult { runs, duration };
64    let hashes_per_second = (result.runs as f64 / result.duration.as_secs_f64())
65        * parallel_count as f64
66        * thread_count as f64;
67
68    print_report(name, hashes_per_second);
69}
70
71fn print_report(name: &str, hashes_per_second: f64) {
72    println!(
73        "{} ran at {}",
74        name,
75        format_hashes_per_second(hashes_per_second)
76    );
77}
78
79fn format_hashes_per_second(hashes_per_second: f64) -> String {
80    let gh_delimiter = 1_000_000_000.0;
81    let mh_delimiter = 1_000_000.0;
82    let kh_delimiter = 1_000.0;
83    if hashes_per_second > gh_delimiter {
84        format!("{:.2}GH/s", hashes_per_second / gh_delimiter)
85    } else if hashes_per_second > mh_delimiter {
86        format!("{:.2}MH/s", hashes_per_second / mh_delimiter)
87    } else if hashes_per_second > kh_delimiter {
88        format!("{:.2}KH/s", hashes_per_second / kh_delimiter)
89    } else {
90        format!("{:.2}H/s", hashes_per_second)
91    }
92}