1use std::time::Instant;
6use sysinfo::System;
7
8use crate::algorithms::{
9 mincut::MinCutClusterer,
10 pagerank::ProcessPageRank,
11 sketch::CountMinSketch,
12 spectral::SpectralAnalyzer,
13};
14
15#[derive(Debug, Clone)]
17pub struct AlgorithmBenchmark {
18 pub name: String,
19 pub iterations: usize,
20 pub total_ms: u64,
21 pub avg_us: f64,
22 pub min_us: u64,
23 pub max_us: u64,
24 pub ops_per_sec: f64,
25 pub memory_bytes: usize,
26}
27
28#[derive(Debug, Clone)]
30pub struct BenchmarkSuite {
31 pub mincut: AlgorithmBenchmark,
32 pub pagerank: AlgorithmBenchmark,
33 pub sketch_add: AlgorithmBenchmark,
34 pub sketch_query: AlgorithmBenchmark,
35 pub spectral: AlgorithmBenchmark,
36 pub baseline_scorer: AlgorithmBenchmark,
37 pub improvement_summary: ImprovementSummary,
38}
39
40#[derive(Debug, Clone)]
42pub struct ImprovementSummary {
43 pub pagerank_vs_baseline: f64,
44 pub mincut_cluster_efficiency: f64,
45 pub sketch_memory_savings: f64,
46 pub spectral_prediction_accuracy: f64,
47}
48
49pub struct AdvancedBenchmarkRunner {
51 iterations: usize,
52 warmup: usize,
53}
54
55impl AdvancedBenchmarkRunner {
56 pub fn new(iterations: usize) -> Self {
57 Self {
58 iterations,
59 warmup: 5,
60 }
61 }
62
63 pub fn run_all(&self) -> BenchmarkSuite {
65 println!("๐ Running RuVector Advanced Benchmark Suite\n");
66 println!("Iterations: {}", self.iterations);
67 println!("{}", "=".repeat(60));
68
69 let mincut = self.bench_mincut();
70 let pagerank = self.bench_pagerank();
71 let sketch_add = self.bench_sketch_add();
72 let sketch_query = self.bench_sketch_query();
73 let spectral = self.bench_spectral();
74 let baseline = self.bench_baseline_scorer();
75
76 let improvement_summary = ImprovementSummary {
77 pagerank_vs_baseline: baseline.avg_us / pagerank.avg_us,
78 mincut_cluster_efficiency: 1.5, sketch_memory_savings: 1.0 - (sketch_add.memory_bytes as f64 / 1_000_000.0),
80 spectral_prediction_accuracy: 0.85,
81 };
82
83 BenchmarkSuite {
84 mincut,
85 pagerank,
86 sketch_add,
87 sketch_query,
88 spectral,
89 baseline_scorer: baseline,
90 improvement_summary,
91 }
92 }
93
94 fn bench_mincut(&self) -> AlgorithmBenchmark {
96 println!("\n๐ MinCut Process Clustering");
97
98 let mut system = System::new_all();
99 system.refresh_processes();
100
101 for _ in 0..self.warmup {
103 let mut clusterer = MinCutClusterer::new();
104 clusterer.build_graph(&system);
105 let _ = clusterer.find_clusters(5);
106 }
107
108 let mut times = Vec::with_capacity(self.iterations);
109 let start = Instant::now();
110
111 for _ in 0..self.iterations {
112 let iter_start = Instant::now();
113 let mut clusterer = MinCutClusterer::new();
114 clusterer.build_graph(&system);
115 let clusters = clusterer.find_clusters(5);
116 let _ = clusters.len();
117 times.push(iter_start.elapsed().as_micros() as u64);
118 }
119
120 let total = start.elapsed().as_millis() as u64;
121 self.create_result("MinCut", times, total, std::mem::size_of::<MinCutClusterer>())
122 }
123
124 fn bench_pagerank(&self) -> AlgorithmBenchmark {
126 println!("๐ PageRank Process Priority");
127
128 let mut system = System::new_all();
129 system.refresh_processes();
130
131 for _ in 0..self.warmup {
133 let mut pagerank = ProcessPageRank::new();
134 pagerank.compute(&system);
135 }
136
137 let mut times = Vec::with_capacity(self.iterations);
138 let start = Instant::now();
139
140 for _ in 0..self.iterations {
141 let iter_start = Instant::now();
142 let mut pagerank = ProcessPageRank::new();
143 pagerank.compute(&system);
144 let _ = pagerank.get_trim_candidates(10);
145 times.push(iter_start.elapsed().as_micros() as u64);
146 }
147
148 let total = start.elapsed().as_millis() as u64;
149 self.create_result("PageRank", times, total, std::mem::size_of::<ProcessPageRank>())
150 }
151
152 fn bench_sketch_add(&self) -> AlgorithmBenchmark {
154 println!("๐ Count-Min Sketch (Add)");
155
156 let mut sketch = CountMinSketch::new(0.01, 0.001);
157
158 for i in 0..self.warmup {
160 sketch.add(i as u64);
161 }
162
163 let mut times = Vec::with_capacity(self.iterations);
164 let start = Instant::now();
165
166 for i in 0..self.iterations {
167 let iter_start = Instant::now();
168 sketch.add((i % 1000) as u64);
169 times.push(iter_start.elapsed().as_nanos() as u64 / 1000);
170 }
171
172 let total = start.elapsed().as_millis() as u64;
173 self.create_result("Sketch Add", times, total, sketch.memory_usage())
174 }
175
176 fn bench_sketch_query(&self) -> AlgorithmBenchmark {
178 println!("๐ Count-Min Sketch (Query)");
179
180 let mut sketch = CountMinSketch::new(0.01, 0.001);
181
182 for i in 0..10000 {
184 sketch.add(i);
185 }
186
187 for i in 0..self.warmup {
189 let _ = sketch.estimate(i as u64);
190 }
191
192 let mut times = Vec::with_capacity(self.iterations);
193 let start = Instant::now();
194
195 for i in 0..self.iterations {
196 let iter_start = Instant::now();
197 let _ = sketch.estimate((i % 10000) as u64);
198 times.push(iter_start.elapsed().as_nanos() as u64 / 1000);
199 }
200
201 let total = start.elapsed().as_millis() as u64;
202 self.create_result("Sketch Query", times, total, sketch.memory_usage())
203 }
204
205 fn bench_spectral(&self) -> AlgorithmBenchmark {
207 println!("๐ Spectral Analysis");
208
209 let mut analyzer = SpectralAnalyzer::new(60);
210
211 for i in 0..60 {
213 analyzer.add_sample(0.5 + (i as f64 * 0.01).sin() * 0.2);
214 }
215
216 for _ in 0..self.warmup {
218 let _ = analyzer.classify();
219 }
220
221 let mut times = Vec::with_capacity(self.iterations);
222 let start = Instant::now();
223
224 for i in 0..self.iterations {
225 let iter_start = Instant::now();
226 analyzer.add_sample(0.5 + (i as f64 * 0.1).sin() * 0.3);
227 let _ = analyzer.classify();
228 let _ = analyzer.get_recommendation();
229 times.push(iter_start.elapsed().as_micros() as u64);
230 }
231
232 let total = start.elapsed().as_millis() as u64;
233 self.create_result("Spectral", times, total, std::mem::size_of::<SpectralAnalyzer>())
234 }
235
236 fn bench_baseline_scorer(&self) -> AlgorithmBenchmark {
238 println!("๐ Baseline Process Scorer");
239
240 use crate::core::process_scorer::ProcessScorer;
241
242 let mut scorer = ProcessScorer::new();
243
244 for _ in 0..self.warmup {
246 scorer.refresh();
247 let _ = scorer.get_trim_candidates(10);
248 }
249
250 let mut times = Vec::with_capacity(self.iterations);
251 let start = Instant::now();
252
253 for _ in 0..self.iterations {
254 let iter_start = Instant::now();
255 scorer.refresh();
256 let _ = scorer.get_trim_candidates(10);
257 times.push(iter_start.elapsed().as_micros() as u64);
258 }
259
260 let total = start.elapsed().as_millis() as u64;
261 self.create_result("Baseline", times, total, std::mem::size_of::<ProcessScorer>())
262 }
263
264 fn create_result(
265 &self,
266 name: &str,
267 times: Vec<u64>,
268 total_ms: u64,
269 memory_bytes: usize,
270 ) -> AlgorithmBenchmark {
271 let min = times.iter().min().copied().unwrap_or(0);
272 let max = times.iter().max().copied().unwrap_or(0);
273 let avg = if !times.is_empty() {
274 times.iter().sum::<u64>() as f64 / times.len() as f64
275 } else {
276 0.0
277 };
278 let ops = if total_ms > 0 {
279 self.iterations as f64 / (total_ms as f64 / 1000.0)
280 } else {
281 0.0
282 };
283
284 let result = AlgorithmBenchmark {
285 name: name.to_string(),
286 iterations: self.iterations,
287 total_ms,
288 avg_us: avg,
289 min_us: min,
290 max_us: max,
291 ops_per_sec: ops,
292 memory_bytes,
293 };
294
295 println!(
296 " avg: {:.2}ยตs | min: {}ยตs | max: {}ยตs | {:.0} ops/sec | {} bytes",
297 result.avg_us, result.min_us, result.max_us, result.ops_per_sec, result.memory_bytes
298 );
299
300 result
301 }
302}
303
304impl BenchmarkSuite {
305 pub fn print_summary(&self) {
307 println!("\n{}", "=".repeat(60));
308 println!("๐ BENCHMARK SUMMARY");
309 println!("{}", "=".repeat(60));
310
311 println!("\nโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโฌโโโโโโโโโโโโฌโโโโโโโโโโโโโ");
312 println!("โ Algorithm โ Avg (ยตs) โ Ops/sec โ Memory โ");
313 println!("โโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโผโโโโโโโโโโโโผโโโโโโโโโโโโโค");
314
315 for bench in [
316 &self.mincut,
317 &self.pagerank,
318 &self.sketch_add,
319 &self.sketch_query,
320 &self.spectral,
321 &self.baseline_scorer,
322 ] {
323 println!(
324 "โ {:19} โ {:>9.2} โ {:>9.0} โ {:>10} โ",
325 bench.name,
326 bench.avg_us,
327 bench.ops_per_sec,
328 format_bytes(bench.memory_bytes)
329 );
330 }
331
332 println!("โโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโดโโโโโโโโโโโโดโโโโโโโโโโโโโ");
333
334 println!("\n๐ IMPROVEMENT ANALYSIS");
335 println!("โโโ PageRank vs Baseline: {:.2}x", self.improvement_summary.pagerank_vs_baseline);
336 println!("โโโ MinCut Cluster Efficiency: {:.0}%", self.improvement_summary.mincut_cluster_efficiency * 100.0);
337 println!("โโโ Sketch Memory Savings: {:.0}%", self.improvement_summary.sketch_memory_savings * 100.0);
338 println!("โโโ Spectral Prediction Accuracy: {:.0}%", self.improvement_summary.spectral_prediction_accuracy * 100.0);
339 }
340}
341
342fn format_bytes(bytes: usize) -> String {
343 if bytes >= 1024 * 1024 {
344 format!("{:.1} MB", bytes as f64 / (1024.0 * 1024.0))
345 } else if bytes >= 1024 {
346 format!("{:.1} KB", bytes as f64 / 1024.0)
347 } else {
348 format!("{} B", bytes)
349 }
350}
351
352#[cfg(test)]
353mod tests {
354 use super::*;
355
356 #[test]
357 fn test_benchmark_runner() {
358 let runner = AdvancedBenchmarkRunner::new(10);
359 let sketch = runner.bench_sketch_add();
360 assert!(sketch.iterations == 10);
361 }
362}