hive_gpu/monitoring/
performance_monitor.rs

1//! Performance Monitoring and Benchmarking
2//!
3//! This module provides performance monitoring, benchmarking, and statistics
4//! collection for GPU operations.
5
6use crate::error::Result;
7use std::collections::HashMap;
8use std::time::{Duration, Instant};
9
10/// Performance Monitor for tracking GPU operation performance
11pub struct PerformanceMonitor {
12    /// Operation statistics
13    stats: HashMap<String, OperationStats>,
14    /// Start time for current operation
15    current_operation: Option<(String, Instant)>,
16}
17
18/// Statistics for a specific operation
19#[derive(Debug, Clone)]
20pub struct OperationStats {
21    /// Operation name
22    pub operation: String,
23    /// Total number of operations
24    pub count: usize,
25    /// Total duration
26    pub total_duration: Duration,
27    /// Average duration
28    pub avg_duration: Duration,
29    /// Minimum duration
30    pub min_duration: Duration,
31    /// Maximum duration
32    pub max_duration: Duration,
33    /// Operations per second
34    pub ops_per_second: f64,
35}
36
37/// Overall performance statistics
38#[derive(Debug, Clone)]
39pub struct PerformanceStats {
40    /// Total operations performed
41    pub total_operations: usize,
42    /// Total duration
43    pub total_duration: Duration,
44    /// Average operations per second
45    pub avg_ops_per_second: f64,
46    /// Operation breakdown
47    pub operation_stats: Vec<OperationStats>,
48}
49
50/// Benchmark result for a specific operation
51#[derive(Debug, Clone)]
52pub struct BenchmarkResult {
53    /// Operation name
54    pub operation: String,
55    /// Duration in milliseconds
56    pub duration_ms: f64,
57    /// Throughput (operations per second)
58    pub throughput: f64,
59    /// Memory usage in bytes
60    pub memory_usage: usize,
61    /// Success rate (0.0-1.0)
62    pub success_rate: f32,
63}
64
65impl PerformanceMonitor {
66    /// Create a new performance monitor
67    pub fn new() -> Self {
68        Self {
69            stats: HashMap::new(),
70            current_operation: None,
71        }
72    }
73
74    /// Start timing an operation
75    pub fn start_operation(&mut self, operation: String) {
76        self.current_operation = Some((operation, Instant::now()));
77    }
78
79    /// End timing the current operation
80    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    /// Record an operation with its duration
93    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    /// Get performance statistics
116    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    /// Get statistics for a specific operation
134    pub fn get_operation_stats(&self, operation: &str) -> Option<&OperationStats> {
135        self.stats.get(operation)
136    }
137
138    /// Clear all statistics
139    pub fn clear_stats(&mut self) {
140        self.stats.clear();
141    }
142
143    /// Generate performance report
144    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}