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}