trustformers_debug/profiler/
io_monitor.rs1#![allow(dead_code)]
6
7use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9use std::time::{Duration, Instant, SystemTime};
10use uuid::Uuid;
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct IoProfile {
15 pub operation_type: IoOperationType,
16 pub file_path: Option<String>,
17 pub bytes_transferred: usize,
18 pub duration: Duration,
19 pub bandwidth_mb_s: f64,
20 pub queue_time: Duration,
21 pub device_type: IoDeviceType,
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
25pub enum IoOperationType {
26 FileRead,
27 FileWrite,
28 NetworkRead,
29 NetworkWrite,
30 DatabaseQuery,
31 CacheLoad,
32 CacheStore,
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
36pub enum IoDeviceType {
37 SSD,
38 HDD,
39 Network,
40 Memory,
41 Cache,
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct LayerLatencyProfile {
47 pub layer_name: String,
48 pub layer_type: String,
49 pub input_shapes: Vec<Vec<usize>>,
50 pub output_shapes: Vec<Vec<usize>>,
51 pub cpu_time: Duration,
52 pub gpu_time: Duration,
53 pub memory_copy_time: Duration,
54 pub sync_time: Duration,
55 pub parameter_count: usize,
56 pub flops: u64,
57 pub memory_footprint_bytes: usize,
58 pub cache_hit_rate: f64,
59}
60
61#[derive(Debug, Serialize, Deserialize)]
62pub struct IoPerformanceSummary {
63 pub total_operations: usize,
64 pub total_bytes_transferred: usize,
65 pub avg_bandwidth_by_device: HashMap<IoDeviceType, f64>,
66 pub slowest_operations: Vec<String>,
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct BandwidthSample {
71 pub timestamp: SystemTime,
72 pub bandwidth_mb_s: f64,
73 pub device_type: IoDeviceType,
74}
75
76#[derive(Debug)]
78pub struct IoMonitor {
79 pub(crate) active_operations: HashMap<Uuid, IoOperation>,
80 pub(crate) bandwidth_history: Vec<BandwidthSample>,
81 pub(crate) io_queue_depth: usize,
82}
83
84#[derive(Debug)]
85pub struct IoOperation {
86 pub(crate) operation_id: Uuid,
87 pub(crate) start_time: Instant,
88 pub(crate) operation_type: IoOperationType,
89 pub(crate) bytes_expected: usize,
90}
91
92impl Default for IoMonitor {
93 fn default() -> Self {
94 Self::new()
95 }
96}
97
98impl IoMonitor {
99 pub fn new() -> Self {
100 Self {
101 active_operations: HashMap::new(),
102 bandwidth_history: Vec::new(),
103 io_queue_depth: 0,
104 }
105 }
106
107 pub fn start_io_operation(
108 &mut self,
109 operation_type: IoOperationType,
110 bytes_expected: usize,
111 ) -> Uuid {
112 let operation_id = Uuid::new_v4();
113 let operation = IoOperation {
114 operation_id,
115 start_time: Instant::now(),
116 operation_type,
117 bytes_expected,
118 };
119
120 self.active_operations.insert(operation_id, operation);
121 self.io_queue_depth += 1;
122 operation_id
123 }
124
125 pub fn finish_io_operation(
126 &mut self,
127 operation_id: Uuid,
128 bytes_transferred: usize,
129 ) -> Option<IoProfile> {
130 if let Some(operation) = self.active_operations.remove(&operation_id) {
131 let duration = operation.start_time.elapsed();
132 let bandwidth_mb_s = if duration.as_secs_f64() > 0.0 {
133 bytes_transferred as f64 / (1024.0 * 1024.0) / duration.as_secs_f64()
134 } else {
135 0.0
136 };
137
138 self.io_queue_depth = self.io_queue_depth.saturating_sub(1);
139
140 let device_type = match operation.operation_type {
141 IoOperationType::FileRead | IoOperationType::FileWrite => IoDeviceType::SSD,
142 IoOperationType::NetworkRead | IoOperationType::NetworkWrite => {
143 IoDeviceType::Network
144 },
145 IoOperationType::CacheLoad | IoOperationType::CacheStore => IoDeviceType::Cache,
146 _ => IoDeviceType::Memory,
147 };
148
149 self.bandwidth_history.push(BandwidthSample {
151 timestamp: SystemTime::now(),
152 bandwidth_mb_s,
153 device_type: device_type.clone(),
154 });
155
156 if self.bandwidth_history.len() > 1000 {
158 self.bandwidth_history.drain(0..500);
159 }
160
161 Some(IoProfile {
162 operation_type: operation.operation_type,
163 file_path: None, bytes_transferred,
165 duration,
166 bandwidth_mb_s,
167 queue_time: Duration::from_millis(self.io_queue_depth as u64 * 10), device_type,
169 })
170 } else {
171 None
172 }
173 }
174
175 pub fn get_average_bandwidth(&self, device_type: &IoDeviceType) -> f64 {
176 let samples: Vec<f64> = self
177 .bandwidth_history
178 .iter()
179 .filter(|s| &s.device_type == device_type)
180 .map(|s| s.bandwidth_mb_s)
181 .collect();
182
183 if samples.is_empty() {
184 0.0
185 } else {
186 samples.iter().sum::<f64>() / samples.len() as f64
187 }
188 }
189}
190
191#[cfg(test)]
192mod tests {
193 use super::*;
194
195 #[test]
196 fn test_io_monitor_new() {
197 let monitor = IoMonitor::new();
198 assert_eq!(monitor.io_queue_depth, 0);
199 assert!(monitor.bandwidth_history.is_empty());
200 }
201
202 #[test]
203 fn test_io_monitor_start_operation() {
204 let mut monitor = IoMonitor::new();
205 let _id = monitor.start_io_operation(IoOperationType::FileRead, 4096);
206 assert_eq!(monitor.io_queue_depth, 1);
207 assert_eq!(monitor.active_operations.len(), 1);
208 }
209
210 #[test]
211 fn test_io_monitor_finish_operation() {
212 let mut monitor = IoMonitor::new();
213 let id = monitor.start_io_operation(IoOperationType::FileWrite, 8192);
214 let profile = monitor.finish_io_operation(id, 8192);
215 assert!(profile.is_some());
216 let p = profile.expect("profile should be Some");
217 assert_eq!(p.bytes_transferred, 8192);
218 assert_eq!(monitor.io_queue_depth, 0);
219 }
220
221 #[test]
222 fn test_io_monitor_finish_nonexistent() {
223 let mut monitor = IoMonitor::new();
224 let profile = monitor.finish_io_operation(Uuid::new_v4(), 100);
225 assert!(profile.is_none());
226 }
227
228 #[test]
229 fn test_io_monitor_average_bandwidth_empty() {
230 let monitor = IoMonitor::new();
231 assert!((monitor.get_average_bandwidth(&IoDeviceType::SSD) - 0.0).abs() < 1e-9);
232 }
233
234 #[test]
235 fn test_io_monitor_device_type_mapping() {
236 let mut monitor = IoMonitor::new();
237 let id = monitor.start_io_operation(IoOperationType::NetworkRead, 1024);
238 let profile = monitor.finish_io_operation(id, 1024);
239 assert!(profile.is_some());
240 let p = profile.expect("profile should be Some");
241 assert_eq!(p.device_type, IoDeviceType::Network);
242 }
243
244 #[test]
245 fn test_io_monitor_cache_device_type() {
246 let mut monitor = IoMonitor::new();
247 let id = monitor.start_io_operation(IoOperationType::CacheLoad, 512);
248 let profile = monitor.finish_io_operation(id, 512);
249 assert!(profile.is_some());
250 let p = profile.expect("profile should be Some");
251 assert_eq!(p.device_type, IoDeviceType::Cache);
252 }
253}