hive_gpu/monitoring/
performance_monitor.rs1use crate::error::Result;
7use std::collections::HashMap;
8use std::time::{Duration, Instant};
9
10pub struct PerformanceMonitor {
12 stats: HashMap<String, OperationStats>,
14 current_operation: Option<(String, Instant)>,
16}
17
18#[derive(Debug, Clone)]
20pub struct OperationStats {
21 pub operation: String,
23 pub count: usize,
25 pub total_duration: Duration,
27 pub avg_duration: Duration,
29 pub min_duration: Duration,
31 pub max_duration: Duration,
33 pub ops_per_second: f64,
35}
36
37#[derive(Debug, Clone)]
39pub struct PerformanceStats {
40 pub total_operations: usize,
42 pub total_duration: Duration,
44 pub avg_ops_per_second: f64,
46 pub operation_stats: Vec<OperationStats>,
48}
49
50#[derive(Debug, Clone)]
52pub struct BenchmarkResult {
53 pub operation: String,
55 pub duration_ms: f64,
57 pub throughput: f64,
59 pub memory_usage: usize,
61 pub success_rate: f32,
63}
64
65impl PerformanceMonitor {
66 pub fn new() -> Self {
68 Self {
69 stats: HashMap::new(),
70 current_operation: None,
71 }
72 }
73
74 pub fn start_operation(&mut self, operation: String) {
76 self.current_operation = Some((operation, Instant::now()));
77 }
78
79 pub fn end_operation(&mut self) -> Result<Duration> {
81 if let Some((operation, start_time)) = self.current_operation.take() {
82 let duration = start_time.elapsed();
83 self.record_operation(operation, duration);
84 Ok(duration)
85 } else {
86 Err(crate::error::HiveGpuError::Other(
87 "No operation in progress".to_string(),
88 ))
89 }
90 }
91
92 pub fn record_operation(&mut self, operation: String, duration: Duration) {
94 let stats = self
95 .stats
96 .entry(operation.clone())
97 .or_insert(OperationStats {
98 operation: operation.clone(),
99 count: 0,
100 total_duration: Duration::ZERO,
101 avg_duration: Duration::ZERO,
102 min_duration: Duration::MAX,
103 max_duration: Duration::ZERO,
104 ops_per_second: 0.0,
105 });
106
107 stats.count += 1;
108 stats.total_duration += duration;
109 stats.avg_duration = stats.total_duration / stats.count as u32;
110 stats.min_duration = stats.min_duration.min(duration);
111 stats.max_duration = stats.max_duration.max(duration);
112 stats.ops_per_second = stats.count as f64 / stats.total_duration.as_secs_f64();
113 }
114
115 pub fn get_performance_stats(&self) -> PerformanceStats {
117 let total_operations: usize = self.stats.values().map(|s| s.count).sum();
118 let total_duration: Duration = self.stats.values().map(|s| s.total_duration).sum();
119 let avg_ops_per_second = if total_duration.as_secs_f64() > 0.0 {
120 total_operations as f64 / total_duration.as_secs_f64()
121 } else {
122 0.0
123 };
124
125 PerformanceStats {
126 total_operations,
127 total_duration,
128 avg_ops_per_second,
129 operation_stats: self.stats.values().cloned().collect(),
130 }
131 }
132
133 pub fn get_operation_stats(&self, operation: &str) -> Option<&OperationStats> {
135 self.stats.get(operation)
136 }
137
138 pub fn clear_stats(&mut self) {
140 self.stats.clear();
141 }
142
143 pub fn generate_report(&self) -> String {
145 let stats = self.get_performance_stats();
146 let mut report = String::new();
147
148 report.push_str("Performance Report:\n");
149 report.push_str(&format!(" Total Operations: {}\n", stats.total_operations));
150 report.push_str(&format!(
151 " Total Duration: {:.2}s\n",
152 stats.total_duration.as_secs_f64()
153 ));
154 report.push_str(&format!(
155 " Average Ops/sec: {:.2}\n",
156 stats.avg_ops_per_second
157 ));
158
159 report.push_str("\nOperation Breakdown:\n");
160 for op_stats in &stats.operation_stats {
161 report.push_str(&format!(" {}:\n", op_stats.operation));
162 report.push_str(&format!(" Count: {}\n", op_stats.count));
163 report.push_str(&format!(
164 " Avg Duration: {:.2}ms\n",
165 op_stats.avg_duration.as_secs_f64() * 1000.0
166 ));
167 report.push_str(&format!(
168 " Min Duration: {:.2}ms\n",
169 op_stats.min_duration.as_secs_f64() * 1000.0
170 ));
171 report.push_str(&format!(
172 " Max Duration: {:.2}ms\n",
173 op_stats.max_duration.as_secs_f64() * 1000.0
174 ));
175 report.push_str(&format!(" Ops/sec: {:.2}\n", op_stats.ops_per_second));
176 }
177
178 report
179 }
180}
181
182impl Default for PerformanceMonitor {
183 fn default() -> Self {
184 Self::new()
185 }
186}