clock_hash/
performance.rs1#[cfg(feature = "std")]
7use std::time::Instant;
8
9#[cfg(feature = "std")]
20pub fn measure_throughput(data_size: usize, iterations: usize) -> f64 {
21 use crate::clockhash256;
22
23 let data = vec![0xAAu8; data_size];
24 let mut total_time = 0u128;
25
26 for _ in 0..10 {
28 let _ = clockhash256(&data);
29 }
30
31 for _ in 0..iterations {
33 let start = Instant::now();
34 let _hash = clockhash256(&data);
35 total_time += start.elapsed().as_nanos();
36 }
37
38 let avg_time_ns = total_time as f64 / iterations as f64;
39 let throughput_mbs = (data_size as f64 / 1_000_000.0) / (avg_time_ns / 1_000_000_000.0);
40
41 throughput_mbs
42}
43
44#[cfg(feature = "std")]
50pub fn benchmark_sizes() -> Vec<(usize, f64)> {
51 let sizes = [64, 1024, 8192, 65536, 524288]; let iterations = [1000, 100, 50, 10, 5]; sizes
55 .iter()
56 .zip(iterations.iter())
57 .map(|(&size, &iters)| (size, measure_throughput(size, iters)))
58 .collect()
59}
60
61#[cfg(feature = "std")]
71pub fn verify_performance(target_throughput: f64) -> bool {
72 let results = benchmark_sizes();
73
74 results
76 .iter()
77 .any(|&(_, throughput)| throughput >= target_throughput)
78}
79
80#[cfg(feature = "std")]
86pub fn performance_stats() -> String {
87 let results = benchmark_sizes();
88
89 let mut stats = String::from("ClockHash-256 Performance Benchmark Results:\n");
90 stats.push_str("Size (bytes) | Throughput (MB/s)\n");
91 stats.push_str("-------------|-----------------\n");
92
93 for &(size, throughput) in &results {
94 stats.push_str(&format!("{:>11} | {:>15.2}\n", size, throughput));
95 }
96
97 if let Some((_, max_throughput)) = results.iter().max_by(|a, b| a.1.partial_cmp(&b.1).unwrap())
99 {
100 stats.push_str(&format!("\nPeak throughput: {:.2} MB/s\n", max_throughput));
101
102 if *max_throughput >= 100.0 {
103 stats.push_str("✓ Performance target met (>= 100 MB/s)\n");
104 } else {
105 stats.push_str("⚠ Performance below target (< 100 MB/s)\n");
106 }
107 }
108
109 stats
110}
111
112pub fn estimate_memory_usage(input_size: usize) -> usize {
122 let hasher_size = 168;
124
125 let input_size = input_size;
127
128 let padding_overhead = 128;
130
131 hasher_size + input_size + padding_overhead
132}
133
134#[cfg(feature = "std")]
140pub fn cpu_features() -> String {
141 let mut features = Vec::new();
142
143 if cfg!(target_feature = "avx2") {
145 features.push("AVX2 available".to_string());
146 } else {
147 features.push("AVX2 not available".to_string());
148 }
149
150 if cfg!(target_feature = "avx512f") {
151 features.push("AVX-512 available".to_string());
152 }
153
154 if let Ok(arch) = std::env::var("CARGO_CFG_TARGET_ARCH") {
155 features.push(format!("Target architecture: {}", arch));
156 }
157
158 features.join(", ")
159}
160
161#[cfg(test)]
162mod tests {
163 use super::*;
164
165 #[test]
166 #[cfg(feature = "std")]
167 fn test_measure_throughput() {
168 let throughput = measure_throughput(1024, 10);
169 assert!(throughput > 0.0, "Throughput should be positive");
170 println!("Measured throughput: {:.2} MB/s", throughput);
171 }
172
173 #[test]
174 #[cfg(feature = "std")]
175 fn test_benchmark_sizes() {
176 let results = benchmark_sizes();
177 assert!(!results.is_empty(), "Should have benchmark results");
178
179 for (size, throughput) in results {
180 assert!(size > 0, "Data size should be positive");
181 assert!(throughput > 0.0, "Throughput should be positive");
182 }
183 }
184
185 #[test]
186 #[cfg(feature = "std")]
187 fn test_performance_stats() {
188 let stats = performance_stats();
189 assert!(!stats.is_empty(), "Performance stats should not be empty");
190 println!("{}", stats);
191 }
192
193 #[test]
194 fn test_estimate_memory_usage() {
195 let usage = estimate_memory_usage(1024);
196 assert!(
197 usage >= 1024,
198 "Memory usage should at least cover input data"
199 );
200
201 let usage_empty = estimate_memory_usage(0);
202 assert!(usage_empty > 0, "Even empty input should use some memory");
203 }
204
205 #[test]
206 #[cfg(feature = "std")]
207 fn test_cpu_features() {
208 let features = cpu_features();
209 assert!(
210 !features.is_empty(),
211 "CPU features string should not be empty"
212 );
213 println!("CPU features: {}", features);
214 }
215
216 #[test]
217 fn test_performance_verification() {
218 #[cfg(feature = "std")]
221 {
222 let meets_target = verify_performance(1.0); if !meets_target {
225 println!("Warning: Performance verification failed (target: 1.0 MB/s)");
226 println!("This may be normal on slow systems or with debug builds");
227 }
228 }
229 }
230}