1use std::time::{Duration, Instant};
4
5pub mod timing_utils {
7 use super::*;
8
9 pub fn measure_time<F, R>(f: F) -> (R, Duration)
11 where
12 F: FnOnce() -> R,
13 {
14 let start = Instant::now();
15 let result = f();
16 let duration = start.elapsed();
17 (result, duration)
18 }
19
20 pub async fn measure_time_async<F, Fut, R>(f: F) -> (R, Duration)
22 where
23 F: FnOnce() -> Fut,
24 Fut: std::future::Future<Output = R>,
25 {
26 let start = Instant::now();
27 let result = f().await;
28 let duration = start.elapsed();
29 (result, duration)
30 }
31
32 pub fn format_duration(duration: Duration) -> String {
34 if duration.as_secs() > 0 {
35 format!("{:.2}s", duration.as_secs_f64())
36 } else if duration.as_millis() > 0 {
37 format!("{:.2}ms", duration.as_millis() as f64)
38 } else {
39 format!("{:.2}μs", duration.as_micros() as f64)
40 }
41 }
42}
43
44pub mod performance_utils {
46 use super::*;
47
48 pub fn calculate_throughput(operations: usize, duration: Duration) -> f64 {
50 if duration.as_secs_f64() > 0.0 {
51 operations as f64 / duration.as_secs_f64()
52 } else {
53 0.0
54 }
55 }
56
57 pub fn calculate_latency(duration: Duration, operations: usize) -> Duration {
59 if operations > 0 {
60 Duration::from_nanos(duration.as_nanos() as u64 / operations as u64)
61 } else {
62 Duration::ZERO
63 }
64 }
65
66 pub fn calculate_efficiency(actual_throughput: f64, theoretical_throughput: f64) -> f32 {
68 if theoretical_throughput > 0.0 {
69 (actual_throughput / theoretical_throughput) as f32
70 } else {
71 0.0
72 }
73 }
74
75 pub fn benchmark_function<F, R>(
77 f: F,
78 iterations: usize,
79 warmup_iterations: usize,
80 ) -> BenchmarkResult
81 where
82 F: Fn() -> R,
83 {
84 for _ in 0..warmup_iterations {
86 let _ = f();
87 }
88
89 let mut durations = Vec::with_capacity(iterations);
91 for _ in 0..iterations {
92 let (_, duration) = timing_utils::measure_time(&f);
93 durations.push(duration);
94 }
95
96 durations.sort();
98 let min_duration = durations[0];
99 let max_duration = durations[iterations - 1];
100 let avg_duration = durations.iter().sum::<Duration>() / iterations as u32;
101 let median_duration = durations[iterations / 2];
102
103 BenchmarkResult {
104 iterations,
105 min_duration,
106 max_duration,
107 avg_duration,
108 median_duration,
109 total_duration: durations.iter().sum(),
110 }
111 }
112}
113
114#[derive(Debug, Clone)]
116pub struct BenchmarkResult {
117 pub iterations: usize,
119 pub min_duration: Duration,
121 pub max_duration: Duration,
123 pub avg_duration: Duration,
125 pub median_duration: Duration,
127 pub total_duration: Duration,
129}