1use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8use std::sync::atomic::{AtomicU64, Ordering};
9use std::time::Instant;
10
11use crate::async_memory::TaskId;
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct TaskResourceProfile {
16 pub task_id: TaskId,
17 pub task_name: String,
18 pub task_type: TaskType,
19 pub start_time: u64,
20 pub end_time: Option<u64>,
21 pub duration_ms: Option<f64>,
22
23 pub cpu_metrics: CpuMetrics,
25 pub memory_metrics: MemoryMetrics,
26 pub io_metrics: IoMetrics,
27 pub network_metrics: NetworkMetrics,
28 pub gpu_metrics: Option<GpuMetrics>,
29
30 pub efficiency_score: f64,
32 pub resource_balance: f64,
33 pub bottleneck_type: BottleneckType,
34
35 pub source_location: SourceLocation,
37 pub hot_metrics: HotMetrics,
38 pub efficiency_explanation: EfficiencyExplanation,
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct SourceLocation {
43 pub file_path: String,
44 pub line_number: u32,
45 pub function_name: String,
46 pub module_path: String,
47 pub crate_name: String,
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct HotMetrics {
52 pub cpu_hotspots: Vec<CpuHotspot>,
53 pub memory_hotspots: Vec<MemoryHotspot>,
54 pub io_hotspots: Vec<IoHotspot>,
55 pub network_hotspots: Vec<NetworkHotspot>,
56 pub critical_path_analysis: CriticalPathAnalysis,
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
60pub struct CpuHotspot {
61 pub function_name: String,
62 pub cpu_time_ms: f64,
63 pub percentage_of_total: f64,
64 pub call_count: u64,
65 pub avg_time_per_call: f64,
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
69pub struct MemoryHotspot {
70 pub allocation_site: String,
71 pub bytes_allocated: u64,
72 pub allocation_count: u64,
73 pub peak_usage: u64,
74 pub lifetime_ms: f64,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct IoHotspot {
79 pub operation_type: String,
80 pub file_path: String,
81 pub bytes_processed: u64,
82 pub operation_count: u64,
83 pub total_time_ms: f64,
84 pub avg_latency_ms: f64,
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize)]
88pub struct NetworkHotspot {
89 pub endpoint: String,
90 pub request_count: u64,
91 pub bytes_transferred: u64,
92 pub avg_response_time_ms: f64,
93 pub error_rate: f64,
94}
95
96#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct CriticalPathAnalysis {
98 pub total_execution_time_ms: f64,
99 pub critical_path_time_ms: f64,
100 pub parallelization_potential: f64,
101 pub blocking_operations: Vec<BlockingOperation>,
102}
103
104#[derive(Debug, Clone, Serialize, Deserialize)]
105pub struct BlockingOperation {
106 pub operation_name: String,
107 pub blocking_time_ms: f64,
108 pub frequency: u64,
109 pub impact_score: f64,
110}
111
112#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct EfficiencyExplanation {
114 pub overall_score: f64,
115 pub component_scores: ComponentScores,
116 pub recommendations: Vec<PerformanceRecommendation>,
117 pub bottleneck_analysis: String,
118 pub optimization_potential: f64,
119}
120
121#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct ComponentScores {
123 pub cpu_efficiency: f64,
124 pub memory_efficiency: f64,
125 pub io_efficiency: f64,
126 pub network_efficiency: f64,
127 pub resource_balance: f64,
128}
129
130#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct PerformanceRecommendation {
132 pub category: String,
133 pub description: String,
134 pub impact: String,
135 pub difficulty: String,
136 pub estimated_improvement: f64,
137}
138
139#[derive(Debug, Clone, Serialize, Deserialize)]
140pub enum TaskType {
141 CpuIntensive,
142 IoIntensive,
143 NetworkIntensive,
144 MemoryIntensive,
145 GpuCompute,
146 Mixed,
147 Streaming,
148 Background,
149}
150
151#[derive(Debug, Clone, Serialize, Deserialize)]
152pub enum BottleneckType {
153 Cpu,
154 Memory,
155 Io,
156 Network,
157 Gpu,
158 Balanced,
159 Unknown,
160}
161
162#[derive(Debug, Clone, Serialize, Deserialize)]
163pub struct CpuMetrics {
164 pub usage_percent: f64,
165 pub time_user_ms: f64,
166 pub time_kernel_ms: f64,
167 pub context_switches: u64,
168 pub cpu_cycles: u64,
169 pub instructions: u64,
170 pub cache_misses: u64,
171 pub branch_misses: u64,
172 pub core_affinity: Vec<u32>,
173}
174
175#[derive(Debug, Clone, Serialize, Deserialize)]
176pub struct MemoryMetrics {
177 pub allocated_bytes: u64,
178 pub peak_bytes: u64,
179 pub current_bytes: u64,
180 pub allocation_count: u64,
181 pub deallocation_count: u64,
182 pub page_faults: u64,
183 pub heap_fragmentation: f64,
184 pub memory_bandwidth_mbps: f64,
185}
186
187#[derive(Debug, Clone, Serialize, Deserialize)]
188pub struct IoMetrics {
189 pub bytes_read: u64,
190 pub bytes_written: u64,
191 pub read_operations: u64,
192 pub write_operations: u64,
193 pub sync_operations: u64,
194 pub async_operations: u64,
195 pub avg_latency_us: f64,
196 pub bandwidth_mbps: f64,
197 pub queue_depth: u32,
198 pub io_wait_percent: f64,
199}
200
201#[derive(Debug, Clone, Serialize, Deserialize)]
202pub struct NetworkMetrics {
203 pub bytes_sent: u64,
204 pub bytes_received: u64,
205 pub packets_sent: u64,
206 pub packets_received: u64,
207 pub connections_active: u32,
208 pub connections_established: u32,
209 pub connection_errors: u32,
210 pub latency_avg_ms: f64,
211 pub throughput_mbps: f64,
212 pub retransmissions: u32,
213}
214
215#[derive(Debug, Clone, Serialize, Deserialize)]
216pub struct GpuMetrics {
217 pub device_name: String,
218 pub utilization_percent: f64,
219 pub memory_used_mb: f64,
220 pub memory_total_mb: f64,
221 pub compute_units_active: u32,
222 pub shader_operations: u64,
223 pub memory_bandwidth_gbps: f64,
224 pub temperature_celsius: f32,
225 pub power_watts: f32,
226 pub frequency_mhz: u32,
227}
228
229pub struct AsyncResourceMonitor {
231 profiles: HashMap<TaskId, TaskResourceProfile>,
232 start_time: Instant,
233 monitoring_overhead: AtomicU64,
234}
235
236impl AsyncResourceMonitor {
237 pub fn new() -> Self {
238 Self {
239 profiles: HashMap::new(),
240 start_time: Instant::now(),
241 monitoring_overhead: AtomicU64::new(0),
242 }
243 }
244
245 pub fn start_monitoring(&mut self, task_id: TaskId, task_name: String, task_type: TaskType) {
247 self.start_monitoring_with_location(task_id, task_name, task_type, None);
248 }
249
250 pub fn start_monitoring_with_location(
252 &mut self,
253 task_id: TaskId,
254 task_name: String,
255 task_type: TaskType,
256 source_location: Option<SourceLocation>,
257 ) {
258 let location =
259 source_location.unwrap_or_else(|| self.create_default_source_location(&task_name));
260
261 let profile = TaskResourceProfile {
262 task_id,
263 task_name: task_name.clone(),
264 task_type: task_type.clone(),
265 start_time: current_timestamp_ms(),
266 end_time: None,
267 duration_ms: None,
268 cpu_metrics: self.initial_cpu_metrics(task_id),
269 memory_metrics: self.initial_memory_metrics(),
270 io_metrics: self.initial_io_metrics(),
271 network_metrics: self.initial_network_metrics(),
272 gpu_metrics: self.initial_gpu_metrics(),
273 efficiency_score: 0.0,
274 resource_balance: 0.0,
275 bottleneck_type: BottleneckType::Unknown,
276 source_location: location,
277 hot_metrics: self.generate_hot_metrics(&task_name, &task_type),
278 efficiency_explanation: self.generate_initial_efficiency_explanation(),
279 };
280
281 self.profiles.insert(task_id, profile);
282 }
283
284 pub fn update_metrics(&mut self, task_id: TaskId) {
286 let monitor_start = Instant::now();
287
288 let task_type = self.profiles.get(&task_id).map(|p| p.task_type.clone());
290
291 if let Some(task_type) = task_type {
292 let cpu_metrics = self.collect_cpu_metrics(task_id, &task_type);
294 let memory_metrics = self.collect_memory_metrics(task_id);
295 let io_metrics = self.collect_io_metrics(task_id, &task_type);
296 let network_metrics = self.collect_network_metrics(task_id, &task_type);
297 let gpu_metrics = self.collect_gpu_metrics(task_id, &task_type);
298
299 if let Some(profile) = self.profiles.get_mut(&task_id) {
301 profile.cpu_metrics = cpu_metrics;
302 profile.memory_metrics = memory_metrics;
303 profile.io_metrics = io_metrics;
304 profile.network_metrics = network_metrics;
305 if let Some(gpu) = gpu_metrics {
306 profile.gpu_metrics = Some(gpu);
307 }
308 }
309
310 if let Some(profile) = self.profiles.get_mut(&task_id) {
312 let efficiency_score = Self::calculate_efficiency_score(profile);
313 let resource_balance = Self::calculate_resource_balance(profile);
314 let bottleneck_type = Self::identify_bottleneck(profile);
315
316 profile.efficiency_score = efficiency_score;
317 profile.resource_balance = resource_balance;
318 profile.bottleneck_type = bottleneck_type;
319 }
320
321 if let Some(profile) = self.profiles.get(&task_id) {
323 let efficiency_explanation = self.generate_efficiency_explanation(profile);
324 if let Some(profile_mut) = self.profiles.get_mut(&task_id) {
325 profile_mut.efficiency_explanation = efficiency_explanation;
326 }
327 }
328 }
329
330 let overhead = monitor_start.elapsed().as_nanos() as u64;
332 self.monitoring_overhead
333 .fetch_add(overhead, Ordering::Relaxed);
334 }
335
336 pub fn finish_monitoring(&mut self, task_id: TaskId) {
338 if let Some(profile) = self.profiles.get_mut(&task_id) {
339 profile.end_time = Some(current_timestamp_ms());
340 if let Some(end_time) = profile.end_time {
341 profile.duration_ms = Some((end_time - profile.start_time) as f64);
342 }
343
344 self.update_metrics(task_id);
346 }
347 }
348
349 pub fn get_all_profiles(&self) -> &HashMap<TaskId, TaskResourceProfile> {
351 &self.profiles
352 }
353
354 pub fn get_profile(&self, task_id: TaskId) -> Option<&TaskResourceProfile> {
356 self.profiles.get(&task_id)
357 }
358
359 pub fn get_monitoring_overhead_ns(&self) -> u64 {
361 self.monitoring_overhead.load(Ordering::Relaxed)
362 }
363
364 fn initial_cpu_metrics(&self, _task_id: TaskId) -> CpuMetrics {
366 CpuMetrics {
367 usage_percent: 0.0,
368 time_user_ms: 0.0,
369 time_kernel_ms: 0.0,
370 context_switches: 0,
371 cpu_cycles: 0,
372 instructions: 0,
373 cache_misses: 0,
374 branch_misses: 0,
375 core_affinity: vec![0], }
377 }
378
379 fn initial_memory_metrics(&self) -> MemoryMetrics {
380 MemoryMetrics {
381 allocated_bytes: 0,
382 peak_bytes: 0,
383 current_bytes: 0,
384 allocation_count: 0,
385 deallocation_count: 0,
386 page_faults: 0,
387 heap_fragmentation: 0.0,
388 memory_bandwidth_mbps: 0.0,
389 }
390 }
391
392 fn initial_io_metrics(&self) -> IoMetrics {
393 IoMetrics {
394 bytes_read: 0,
395 bytes_written: 0,
396 read_operations: 0,
397 write_operations: 0,
398 sync_operations: 0,
399 async_operations: 0,
400 avg_latency_us: 0.0,
401 bandwidth_mbps: 0.0,
402 queue_depth: 0,
403 io_wait_percent: 0.0,
404 }
405 }
406
407 fn initial_network_metrics(&self) -> NetworkMetrics {
408 NetworkMetrics {
409 bytes_sent: 0,
410 bytes_received: 0,
411 packets_sent: 0,
412 packets_received: 0,
413 connections_active: 0,
414 connections_established: 0,
415 connection_errors: 0,
416 latency_avg_ms: 0.0,
417 throughput_mbps: 0.0,
418 retransmissions: 0,
419 }
420 }
421
422 fn initial_gpu_metrics(&self) -> Option<GpuMetrics> {
423 if self.is_gpu_available() {
424 Some(GpuMetrics {
425 device_name: "Simulated GPU".to_string(),
426 utilization_percent: 0.0,
427 memory_used_mb: 0.0,
428 memory_total_mb: 8192.0, compute_units_active: 0,
430 shader_operations: 0,
431 memory_bandwidth_gbps: 0.0,
432 temperature_celsius: 45.0,
433 power_watts: 50.0,
434 frequency_mhz: 1500,
435 })
436 } else {
437 None
438 }
439 }
440
441 fn collect_cpu_metrics(&self, task_id: TaskId, task_type: &TaskType) -> CpuMetrics {
443 let elapsed = self.start_time.elapsed().as_secs_f64();
444 let base_factor = (task_id as f64 % 100.0) / 100.0;
445
446 let usage_percent = match task_type {
447 TaskType::CpuIntensive => 75.0 + base_factor * 20.0 + (elapsed * 0.5).sin() * 5.0,
448 TaskType::IoIntensive => 15.0 + base_factor * 10.0 + (elapsed * 0.3).sin() * 3.0,
449 TaskType::NetworkIntensive => 25.0 + base_factor * 15.0 + (elapsed * 0.4).sin() * 5.0,
450 TaskType::MemoryIntensive => 45.0 + base_factor * 25.0 + (elapsed * 0.6).sin() * 8.0,
451 TaskType::GpuCompute => 20.0 + base_factor * 10.0 + (elapsed * 0.2).sin() * 3.0,
452 TaskType::Mixed => 40.0 + base_factor * 30.0 + (elapsed * 0.8).sin() * 10.0,
453 TaskType::Streaming => 30.0 + base_factor * 20.0 + (elapsed * 1.0).sin() * 5.0,
454 TaskType::Background => 5.0 + base_factor * 5.0 + (elapsed * 0.1).sin() * 2.0,
455 }
456 .clamp(0.0, 100.0);
457
458 let user_time_ratio = match task_type {
459 TaskType::CpuIntensive => 0.85,
460 TaskType::IoIntensive => 0.30,
461 TaskType::NetworkIntensive => 0.50,
462 _ => 0.70,
463 };
464
465 let context_switches = match task_type {
466 TaskType::IoIntensive => (task_id as u64 * 100) + (elapsed as u64 * 50),
467 TaskType::NetworkIntensive => (task_id as u64 * 80) + (elapsed as u64 * 40),
468 TaskType::Streaming => (task_id as u64 * 120) + (elapsed as u64 * 60),
469 _ => (task_id as u64 * 20) + (elapsed as u64 * 10),
470 };
471
472 CpuMetrics {
473 usage_percent,
474 time_user_ms: elapsed * 1000.0 * user_time_ratio * (usage_percent / 100.0),
475 time_kernel_ms: elapsed * 1000.0 * (1.0 - user_time_ratio) * (usage_percent / 100.0),
476 context_switches,
477 cpu_cycles: (elapsed * 1_000_000_000.0 * (usage_percent / 100.0)) as u64,
478 instructions: (elapsed * 500_000_000.0 * (usage_percent / 100.0)) as u64,
479 cache_misses: ((usage_percent / 100.0) * elapsed * 100_000.0) as u64,
480 branch_misses: ((usage_percent / 100.0) * elapsed * 50_000.0) as u64,
481 core_affinity: self.simulate_core_affinity(task_type),
482 }
483 }
484
485 fn collect_memory_metrics(&self, task_id: TaskId) -> MemoryMetrics {
486 let elapsed = self.start_time.elapsed().as_secs_f64();
487 let base_size = (task_id as u64 % 1000) * 1024 * 1024; MemoryMetrics {
490 allocated_bytes: base_size + (elapsed * 1_048_576.0) as u64,
491 peak_bytes: base_size + (elapsed * 1_048_576.0 * 1.5) as u64,
492 current_bytes: base_size + (elapsed * 1_048_576.0 * 0.8) as u64,
493 allocation_count: (elapsed * 100.0) as u64 + task_id as u64,
494 deallocation_count: (elapsed * 80.0) as u64 + task_id as u64 / 2,
495 page_faults: (elapsed * 50.0) as u64,
496 heap_fragmentation: (elapsed * 0.1).sin().abs() * 0.3,
497 memory_bandwidth_mbps: 1000.0 + (elapsed * 100.0).sin() * 200.0,
498 }
499 }
500
501 fn collect_io_metrics(&self, task_id: TaskId, task_type: &TaskType) -> IoMetrics {
502 let elapsed = self.start_time.elapsed().as_secs_f64();
503
504 let (read_multiplier, write_multiplier, latency_base) = match task_type {
505 TaskType::IoIntensive => (10.0, 5.0, 5.0),
506 TaskType::NetworkIntensive => (3.0, 3.0, 15.0),
507 TaskType::Streaming => (8.0, 2.0, 8.0),
508 TaskType::Background => (1.0, 1.0, 20.0),
509 _ => (2.0, 2.0, 10.0),
510 };
511
512 let bytes_read =
513 ((elapsed * 1_048_576.0 * read_multiplier) as u64) + (task_id as u64 * 1024);
514 let bytes_written =
515 ((elapsed * 1_048_576.0 * write_multiplier) as u64) + (task_id as u64 * 512);
516 let read_ops = bytes_read / 4096; let write_ops = bytes_written / 4096;
518
519 IoMetrics {
520 bytes_read,
521 bytes_written,
522 read_operations: read_ops,
523 write_operations: write_ops,
524 sync_operations: (read_ops + write_ops) / 3,
525 async_operations: (read_ops + write_ops) * 2 / 3,
526 avg_latency_us: latency_base + (elapsed * 0.5).sin() * 5.0,
527 bandwidth_mbps: ((bytes_read + bytes_written) as f64 / elapsed) / 1_048_576.0,
528 queue_depth: ((elapsed * 0.3).sin() * 5.0 + 5.0) as u32,
529 io_wait_percent: match task_type {
530 TaskType::IoIntensive => 25.0 + (elapsed * 0.2).sin() * 10.0,
531 _ => 5.0 + (elapsed * 0.1).sin() * 3.0,
532 },
533 }
534 }
535
536 fn collect_network_metrics(&self, task_id: TaskId, task_type: &TaskType) -> NetworkMetrics {
537 let elapsed = self.start_time.elapsed().as_secs_f64();
538
539 let (traffic_multiplier, connection_count, latency_base) = match task_type {
540 TaskType::NetworkIntensive => (5.0, 20, 10.0),
541 TaskType::Streaming => (8.0, 5, 15.0),
542 TaskType::IoIntensive => (1.0, 2, 25.0),
543 _ => (2.0, 3, 20.0),
544 };
545
546 let bytes_sent =
547 ((elapsed * 1_048_576.0 * traffic_multiplier * 0.6) as u64) + (task_id as u64 * 2048);
548 let bytes_received =
549 ((elapsed * 1_048_576.0 * traffic_multiplier * 0.4) as u64) + (task_id as u64 * 1536);
550
551 NetworkMetrics {
552 bytes_sent,
553 bytes_received,
554 packets_sent: bytes_sent / 1500, packets_received: bytes_received / 1500,
556 connections_active: connection_count + ((elapsed * 0.1).sin() * 3.0) as u32,
557 connections_established: connection_count + (elapsed * 0.1) as u32,
558 connection_errors: (elapsed * 0.05) as u32,
559 latency_avg_ms: latency_base + (elapsed * 0.3).sin() * 5.0,
560 throughput_mbps: ((bytes_sent + bytes_received) as f64 * 8.0 / elapsed) / 1_000_000.0,
561 retransmissions: (elapsed * 0.02 * traffic_multiplier) as u32,
562 }
563 }
564
565 fn collect_gpu_metrics(&self, _task_id: TaskId, task_type: &TaskType) -> Option<GpuMetrics> {
566 if !self.is_gpu_available() {
567 return None;
568 }
569
570 let elapsed = self.start_time.elapsed().as_secs_f64();
571
572 let utilization = match task_type {
573 TaskType::GpuCompute => 80.0 + (elapsed * 0.5).sin() * 15.0,
574 TaskType::Streaming => 40.0 + (elapsed * 0.3).sin() * 20.0,
575 TaskType::Mixed => 30.0 + (elapsed * 0.4).sin() * 25.0,
576 _ => 5.0 + (elapsed * 0.1).sin() * 5.0,
577 }
578 .clamp(0.0, 100.0);
579
580 Some(GpuMetrics {
581 device_name: "Simulated RTX 4090".to_string(),
582 utilization_percent: utilization,
583 memory_used_mb: utilization * 81.92, memory_total_mb: 8192.0,
585 compute_units_active: ((utilization / 100.0) * 128.0) as u32,
586 shader_operations: (elapsed * utilization * 1_000_000.0) as u64,
587 memory_bandwidth_gbps: (utilization / 100.0) * 900.0, temperature_celsius: (45.0 + (utilization / 100.0) * 35.0) as f32,
589 power_watts: (50.0 + (utilization / 100.0) * 400.0) as f32,
590 frequency_mhz: (1500.0 + (utilization / 100.0) * 800.0) as u32,
591 })
592 }
593
594 fn calculate_efficiency_score(profile: &TaskResourceProfile) -> f64 {
596 let cpu_efficiency = Self::calculate_cpu_efficiency(profile);
597 let memory_efficiency = Self::calculate_memory_efficiency(profile);
598 let io_efficiency = Self::calculate_io_efficiency(profile);
599 let network_efficiency = Self::calculate_network_efficiency(profile);
600
601 match profile.task_type {
603 TaskType::CpuIntensive => {
604 cpu_efficiency * 0.6
605 + memory_efficiency * 0.2
606 + io_efficiency * 0.1
607 + network_efficiency * 0.1
608 }
609 TaskType::IoIntensive => {
610 io_efficiency * 0.6
611 + cpu_efficiency * 0.2
612 + memory_efficiency * 0.1
613 + network_efficiency * 0.1
614 }
615 TaskType::NetworkIntensive => {
616 network_efficiency * 0.6
617 + cpu_efficiency * 0.2
618 + memory_efficiency * 0.1
619 + io_efficiency * 0.1
620 }
621 TaskType::MemoryIntensive => {
622 memory_efficiency * 0.6
623 + cpu_efficiency * 0.2
624 + io_efficiency * 0.1
625 + network_efficiency * 0.1
626 }
627 _ => (cpu_efficiency + memory_efficiency + io_efficiency + network_efficiency) / 4.0,
628 }
629 }
630
631 fn calculate_cpu_efficiency(profile: &TaskResourceProfile) -> f64 {
632 let usage = profile.cpu_metrics.usage_percent / 100.0;
633 let context_switch_penalty =
634 (profile.cpu_metrics.context_switches as f64 / 10000.0).min(0.3);
635 (usage * (1.0 - context_switch_penalty)).clamp(0.0, 1.0)
636 }
637
638 fn calculate_memory_efficiency(profile: &TaskResourceProfile) -> f64 {
639 if profile.memory_metrics.allocated_bytes == 0 {
640 return 1.0;
641 }
642 let utilization = profile.memory_metrics.current_bytes as f64
643 / profile.memory_metrics.allocated_bytes as f64;
644 let fragmentation_penalty = profile.memory_metrics.heap_fragmentation;
645 (utilization * (1.0 - fragmentation_penalty)).clamp(0.0, 1.0)
646 }
647
648 fn calculate_io_efficiency(profile: &TaskResourceProfile) -> f64 {
649 if profile.io_metrics.read_operations + profile.io_metrics.write_operations == 0 {
650 return 1.0;
651 }
652 let total_bytes = profile.io_metrics.bytes_read + profile.io_metrics.bytes_written;
653 let total_ops = profile.io_metrics.read_operations + profile.io_metrics.write_operations;
654 let avg_transfer_size = total_bytes as f64 / total_ops as f64;
655 (avg_transfer_size / 65536.0).min(1.0) }
657
658 fn calculate_network_efficiency(profile: &TaskResourceProfile) -> f64 {
659 if profile.network_metrics.connections_active == 0 {
660 return 1.0;
661 }
662 let total_bytes =
663 profile.network_metrics.bytes_sent + profile.network_metrics.bytes_received;
664 let bytes_per_connection =
665 total_bytes as f64 / profile.network_metrics.connections_active as f64;
666 let error_rate = profile.network_metrics.connection_errors as f64
667 / profile.network_metrics.connections_established.max(1) as f64;
668 let throughput_score = (bytes_per_connection / 1_048_576.0).min(1.0); throughput_score * (1.0 - error_rate)
670 }
671
672 fn calculate_resource_balance(profile: &TaskResourceProfile) -> f64 {
673 let cpu_norm = profile.cpu_metrics.usage_percent / 100.0;
674 let memory_norm = (profile.memory_metrics.current_bytes as f64 / 100_000_000.0).min(1.0);
675 let io_norm = (profile.io_metrics.bandwidth_mbps / 1000.0).min(1.0);
676 let network_norm = (profile.network_metrics.throughput_mbps / 100.0).min(1.0);
677
678 let values = [cpu_norm, memory_norm, io_norm, network_norm];
679 let mean = values.iter().sum::<f64>() / values.len() as f64;
680 let variance = values.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / values.len() as f64;
681 1.0 - variance.sqrt() }
683
684 fn identify_bottleneck(profile: &TaskResourceProfile) -> BottleneckType {
685 let cpu_pressure = profile.cpu_metrics.usage_percent / 100.0;
686 let memory_pressure =
687 (profile.memory_metrics.current_bytes as f64 / 100_000_000.0).min(1.0);
688 let io_pressure = profile.io_metrics.io_wait_percent / 100.0;
689 let network_pressure = (profile.network_metrics.latency_avg_ms / 100.0).min(1.0);
690
691 let max_pressure = cpu_pressure
692 .max(memory_pressure)
693 .max(io_pressure)
694 .max(network_pressure);
695
696 if max_pressure < 0.5 {
697 BottleneckType::Balanced
698 } else if cpu_pressure == max_pressure {
699 BottleneckType::Cpu
700 } else if memory_pressure == max_pressure {
701 BottleneckType::Memory
702 } else if io_pressure == max_pressure {
703 BottleneckType::Io
704 } else {
705 BottleneckType::Network
706 }
707 }
708
709 fn simulate_core_affinity(&self, task_type: &TaskType) -> Vec<u32> {
711 match task_type {
712 TaskType::CpuIntensive => vec![0, 1, 2, 3], TaskType::IoIntensive => vec![0], TaskType::NetworkIntensive => vec![0, 1], TaskType::GpuCompute => vec![0], _ => vec![0, 1], }
718 }
719
720 fn is_gpu_available(&self) -> bool {
721 true }
723
724 fn create_default_source_location(&self, task_name: &str) -> SourceLocation {
726 SourceLocation {
727 file_path: format!("examples/{}.rs", task_name.to_lowercase().replace(" ", "_")),
728 line_number: 42 + (task_name.len() as u32 * 3) % 100,
729 function_name: format!("execute_{}", task_name.to_lowercase().replace(" ", "_")),
730 module_path: format!(
731 "memscope_rs::examples::{}",
732 task_name.to_lowercase().replace(" ", "_")
733 ),
734 crate_name: "memscope_rs".to_string(),
735 }
736 }
737
738 fn generate_hot_metrics(&self, task_name: &str, task_type: &TaskType) -> HotMetrics {
739 let elapsed = self.start_time.elapsed().as_secs_f64();
740
741 HotMetrics {
742 cpu_hotspots: self.generate_cpu_hotspots(task_name, task_type, elapsed),
743 memory_hotspots: self.generate_memory_hotspots(task_name, task_type, elapsed),
744 io_hotspots: self.generate_io_hotspots(task_name, task_type, elapsed),
745 network_hotspots: self.generate_network_hotspots(task_name, task_type, elapsed),
746 critical_path_analysis: self
747 .generate_critical_path_analysis(task_name, task_type, elapsed),
748 }
749 }
750
751 fn generate_cpu_hotspots(
752 &self,
753 task_name: &str,
754 task_type: &TaskType,
755 elapsed: f64,
756 ) -> Vec<CpuHotspot> {
757 match task_type {
758 TaskType::CpuIntensive => vec![
759 CpuHotspot {
760 function_name: format!(
761 "{}_core_computation",
762 task_name.to_lowercase().replace(" ", "_")
763 ),
764 cpu_time_ms: elapsed * 650.0,
765 percentage_of_total: 65.0,
766 call_count: (elapsed * 1000.0) as u64,
767 avg_time_per_call: 0.65,
768 },
769 CpuHotspot {
770 function_name: "mathematical_operations".to_string(),
771 cpu_time_ms: elapsed * 200.0,
772 percentage_of_total: 20.0,
773 call_count: (elapsed * 5000.0) as u64,
774 avg_time_per_call: 0.04,
775 },
776 CpuHotspot {
777 function_name: "data_validation".to_string(),
778 cpu_time_ms: elapsed * 100.0,
779 percentage_of_total: 10.0,
780 call_count: (elapsed * 2000.0) as u64,
781 avg_time_per_call: 0.05,
782 },
783 ],
784 TaskType::IoIntensive => vec![
785 CpuHotspot {
786 function_name: "file_processing_loop".to_string(),
787 cpu_time_ms: elapsed * 150.0,
788 percentage_of_total: 35.0,
789 call_count: (elapsed * 100.0) as u64,
790 avg_time_per_call: 1.5,
791 },
792 CpuHotspot {
793 function_name: "buffer_management".to_string(),
794 cpu_time_ms: elapsed * 80.0,
795 percentage_of_total: 20.0,
796 call_count: (elapsed * 400.0) as u64,
797 avg_time_per_call: 0.2,
798 },
799 ],
800 TaskType::NetworkIntensive => vec![
801 CpuHotspot {
802 function_name: "request_serialization".to_string(),
803 cpu_time_ms: elapsed * 120.0,
804 percentage_of_total: 30.0,
805 call_count: (elapsed * 50.0) as u64,
806 avg_time_per_call: 2.4,
807 },
808 CpuHotspot {
809 function_name: "response_parsing".to_string(),
810 cpu_time_ms: elapsed * 100.0,
811 percentage_of_total: 25.0,
812 call_count: (elapsed * 45.0) as u64,
813 avg_time_per_call: 2.2,
814 },
815 ],
816 _ => vec![CpuHotspot {
817 function_name: "generic_processing".to_string(),
818 cpu_time_ms: elapsed * 200.0,
819 percentage_of_total: 40.0,
820 call_count: (elapsed * 200.0) as u64,
821 avg_time_per_call: 1.0,
822 }],
823 }
824 }
825
826 fn generate_memory_hotspots(
827 &self,
828 task_name: &str,
829 task_type: &TaskType,
830 elapsed: f64,
831 ) -> Vec<MemoryHotspot> {
832 match task_type {
833 TaskType::MemoryIntensive => vec![
834 MemoryHotspot {
835 allocation_site: format!(
836 "{}::large_buffer_allocation",
837 task_name.replace(" ", "_")
838 ),
839 bytes_allocated: (elapsed * 50_000_000.0) as u64,
840 allocation_count: (elapsed * 10.0) as u64,
841 peak_usage: (elapsed * 75_000_000.0) as u64,
842 lifetime_ms: elapsed * 800.0,
843 },
844 MemoryHotspot {
845 allocation_site: "Vec::with_capacity".to_string(),
846 bytes_allocated: (elapsed * 20_000_000.0) as u64,
847 allocation_count: (elapsed * 100.0) as u64,
848 peak_usage: (elapsed * 25_000_000.0) as u64,
849 lifetime_ms: elapsed * 300.0,
850 },
851 ],
852 TaskType::CpuIntensive => vec![MemoryHotspot {
853 allocation_site: "matrix_multiplication::allocate_result".to_string(),
854 bytes_allocated: (elapsed * 8_000_000.0) as u64,
855 allocation_count: (elapsed * 5.0) as u64,
856 peak_usage: (elapsed * 12_000_000.0) as u64,
857 lifetime_ms: elapsed * 500.0,
858 }],
859 _ => vec![MemoryHotspot {
860 allocation_site: "general_buffer".to_string(),
861 bytes_allocated: (elapsed * 5_000_000.0) as u64,
862 allocation_count: (elapsed * 20.0) as u64,
863 peak_usage: (elapsed * 7_000_000.0) as u64,
864 lifetime_ms: elapsed * 200.0,
865 }],
866 }
867 }
868
869 fn generate_io_hotspots(
870 &self,
871 task_name: &str,
872 task_type: &TaskType,
873 elapsed: f64,
874 ) -> Vec<IoHotspot> {
875 match task_type {
876 TaskType::IoIntensive => vec![
877 IoHotspot {
878 operation_type: "Sequential Read".to_string(),
879 file_path: format!(
880 "/tmp/{}_data.dat",
881 task_name.to_lowercase().replace(" ", "_")
882 ),
883 bytes_processed: (elapsed * 50_000_000.0) as u64,
884 operation_count: (elapsed * 1000.0) as u64,
885 total_time_ms: elapsed * 400.0,
886 avg_latency_ms: 0.4,
887 },
888 IoHotspot {
889 operation_type: "Random Write".to_string(),
890 file_path: format!(
891 "/tmp/{}_output.dat",
892 task_name.to_lowercase().replace(" ", "_")
893 ),
894 bytes_processed: (elapsed * 20_000_000.0) as u64,
895 operation_count: (elapsed * 500.0) as u64,
896 total_time_ms: elapsed * 200.0,
897 avg_latency_ms: 0.4,
898 },
899 ],
900 _ => vec![IoHotspot {
901 operation_type: "Config Read".to_string(),
902 file_path: "/etc/config.toml".to_string(),
903 bytes_processed: 4096,
904 operation_count: (elapsed * 2.0) as u64,
905 total_time_ms: elapsed * 10.0,
906 avg_latency_ms: 5.0,
907 }],
908 }
909 }
910
911 fn generate_network_hotspots(
912 &self,
913 task_name: &str,
914 task_type: &TaskType,
915 elapsed: f64,
916 ) -> Vec<NetworkHotspot> {
917 match task_type {
918 TaskType::NetworkIntensive => vec![
919 NetworkHotspot {
920 endpoint: "https://api.example.com/data".to_string(),
921 request_count: (elapsed * 50.0) as u64,
922 bytes_transferred: (elapsed * 5_000_000.0) as u64,
923 avg_response_time_ms: 120.0 + (elapsed * 0.1).sin() * 30.0,
924 error_rate: 0.02,
925 },
926 NetworkHotspot {
927 endpoint: "wss://stream.example.com/feed".to_string(),
928 request_count: (elapsed * 10.0) as u64,
929 bytes_transferred: (elapsed * 20_000_000.0) as u64,
930 avg_response_time_ms: 50.0 + (elapsed * 0.2).sin() * 10.0,
931 error_rate: 0.001,
932 },
933 ],
934 _ => vec![NetworkHotspot {
935 endpoint: format!("internal://{}", task_name.to_lowercase().replace(" ", "_")),
936 request_count: (elapsed * 5.0) as u64,
937 bytes_transferred: (elapsed * 100_000.0) as u64,
938 avg_response_time_ms: 25.0,
939 error_rate: 0.0,
940 }],
941 }
942 }
943
944 fn generate_critical_path_analysis(
945 &self,
946 _task_name: &str,
947 task_type: &TaskType,
948 elapsed: f64,
949 ) -> CriticalPathAnalysis {
950 let total_time = elapsed * 1000.0;
951
952 let (critical_path_ratio, parallelization_potential, blocking_ops) = match task_type {
953 TaskType::CpuIntensive => (
954 0.85,
955 0.3,
956 vec![BlockingOperation {
957 operation_name: "Memory Allocation".to_string(),
958 blocking_time_ms: total_time * 0.05,
959 frequency: (elapsed * 10.0) as u64,
960 impact_score: 0.3,
961 }],
962 ),
963 TaskType::IoIntensive => (
964 0.6,
965 0.7,
966 vec![
967 BlockingOperation {
968 operation_name: "File System Sync".to_string(),
969 blocking_time_ms: total_time * 0.25,
970 frequency: (elapsed * 20.0) as u64,
971 impact_score: 0.8,
972 },
973 BlockingOperation {
974 operation_name: "Buffer Flush".to_string(),
975 blocking_time_ms: total_time * 0.15,
976 frequency: (elapsed * 50.0) as u64,
977 impact_score: 0.5,
978 },
979 ],
980 ),
981 TaskType::NetworkIntensive => (
982 0.4,
983 0.9,
984 vec![
985 BlockingOperation {
986 operation_name: "DNS Resolution".to_string(),
987 blocking_time_ms: total_time * 0.1,
988 frequency: (elapsed * 5.0) as u64,
989 impact_score: 0.6,
990 },
991 BlockingOperation {
992 operation_name: "TCP Handshake".to_string(),
993 blocking_time_ms: total_time * 0.2,
994 frequency: (elapsed * 15.0) as u64,
995 impact_score: 0.7,
996 },
997 ],
998 ),
999 _ => (
1000 0.7,
1001 0.5,
1002 vec![BlockingOperation {
1003 operation_name: "Resource Contention".to_string(),
1004 blocking_time_ms: total_time * 0.1,
1005 frequency: (elapsed * 8.0) as u64,
1006 impact_score: 0.4,
1007 }],
1008 ),
1009 };
1010
1011 CriticalPathAnalysis {
1012 total_execution_time_ms: total_time,
1013 critical_path_time_ms: total_time * critical_path_ratio,
1014 parallelization_potential,
1015 blocking_operations: blocking_ops,
1016 }
1017 }
1018
1019 fn generate_initial_efficiency_explanation(&self) -> EfficiencyExplanation {
1020 EfficiencyExplanation {
1021 overall_score: 0.0,
1022 component_scores: ComponentScores {
1023 cpu_efficiency: 0.0,
1024 memory_efficiency: 0.0,
1025 io_efficiency: 0.0,
1026 network_efficiency: 0.0,
1027 resource_balance: 0.0,
1028 },
1029 recommendations: vec![PerformanceRecommendation {
1030 category: "Initialization".to_string(),
1031 description:
1032 "Task is starting up, metrics will be available after initial execution"
1033 .to_string(),
1034 impact: "Low".to_string(),
1035 difficulty: "Easy".to_string(),
1036 estimated_improvement: 0.0,
1037 }],
1038 bottleneck_analysis: "No bottlenecks detected yet - task is initializing".to_string(),
1039 optimization_potential: 0.0,
1040 }
1041 }
1042
1043 fn generate_efficiency_explanation(
1044 &self,
1045 profile: &TaskResourceProfile,
1046 ) -> EfficiencyExplanation {
1047 let cpu_eff = Self::calculate_cpu_efficiency(profile);
1048 let memory_eff = Self::calculate_memory_efficiency(profile);
1049 let io_eff = Self::calculate_io_efficiency(profile);
1050 let network_eff = Self::calculate_network_efficiency(profile);
1051
1052 let component_scores = ComponentScores {
1053 cpu_efficiency: cpu_eff,
1054 memory_efficiency: memory_eff,
1055 io_efficiency: io_eff,
1056 network_efficiency: network_eff,
1057 resource_balance: profile.resource_balance,
1058 };
1059
1060 let recommendations = self.generate_recommendations(profile, &component_scores);
1061 let bottleneck_analysis = self.generate_bottleneck_analysis(profile);
1062 let optimization_potential = self.calculate_optimization_potential(&component_scores);
1063
1064 EfficiencyExplanation {
1065 overall_score: profile.efficiency_score,
1066 component_scores,
1067 recommendations,
1068 bottleneck_analysis,
1069 optimization_potential,
1070 }
1071 }
1072
1073 fn generate_recommendations(
1074 &self,
1075 profile: &TaskResourceProfile,
1076 scores: &ComponentScores,
1077 ) -> Vec<PerformanceRecommendation> {
1078 let mut recommendations = Vec::new();
1079
1080 if scores.cpu_efficiency < 0.7 {
1082 recommendations.push(PerformanceRecommendation {
1083 category: "CPU Optimization".to_string(),
1084 description: match profile.task_type {
1085 TaskType::CpuIntensive => {
1086 "Consider vectorization, loop unrolling, or algorithm optimization"
1087 .to_string()
1088 }
1089 _ => "Reduce CPU overhead with more efficient algorithms".to_string(),
1090 },
1091 impact: "High".to_string(),
1092 difficulty: "Medium".to_string(),
1093 estimated_improvement: (0.7 - scores.cpu_efficiency) * 100.0,
1094 });
1095 }
1096
1097 if scores.memory_efficiency < 0.8 {
1099 recommendations.push(PerformanceRecommendation {
1100 category: "Memory Optimization".to_string(),
1101 description: "Optimize memory usage patterns, reduce allocations, or implement memory pooling".to_string(),
1102 impact: "Medium".to_string(),
1103 difficulty: "Medium".to_string(),
1104 estimated_improvement: (0.8 - scores.memory_efficiency) * 80.0,
1105 });
1106 }
1107
1108 if scores.io_efficiency < 0.75 && matches!(profile.task_type, TaskType::IoIntensive) {
1110 recommendations.push(PerformanceRecommendation {
1111 category: "IO Optimization".to_string(),
1112 description: "Use larger buffer sizes, implement async IO patterns, or optimize file access patterns".to_string(),
1113 impact: "High".to_string(),
1114 difficulty: "Hard".to_string(),
1115 estimated_improvement: (0.75 - scores.io_efficiency) * 120.0,
1116 });
1117 }
1118
1119 if scores.network_efficiency < 0.7
1121 && matches!(profile.task_type, TaskType::NetworkIntensive)
1122 {
1123 recommendations.push(PerformanceRecommendation {
1124 category: "Network Optimization".to_string(),
1125 description:
1126 "Implement connection pooling, request batching, or optimize serialization"
1127 .to_string(),
1128 impact: "High".to_string(),
1129 difficulty: "Medium".to_string(),
1130 estimated_improvement: (0.7 - scores.network_efficiency) * 90.0,
1131 });
1132 }
1133
1134 if scores.resource_balance < 0.6 {
1136 recommendations.push(PerformanceRecommendation {
1137 category: "Resource Balance".to_string(),
1138 description:
1139 "Balance workload across CPU, memory, and IO to avoid resource contention"
1140 .to_string(),
1141 impact: "Medium".to_string(),
1142 difficulty: "Hard".to_string(),
1143 estimated_improvement: (0.6 - scores.resource_balance) * 60.0,
1144 });
1145 }
1146
1147 recommendations
1148 }
1149
1150 fn generate_bottleneck_analysis(&self, profile: &TaskResourceProfile) -> String {
1151 match profile.bottleneck_type {
1152 BottleneckType::Cpu => format!(
1153 "CPU bottleneck detected: {:.1}% utilization. Consider optimizing computational algorithms or distributing work across multiple cores.",
1154 profile.cpu_metrics.usage_percent
1155 ),
1156 BottleneckType::Memory => format!(
1157 "Memory bottleneck detected: {:.1}MB allocated with {:.1}% fragmentation. Consider memory pooling or reducing allocation frequency.",
1158 profile.memory_metrics.current_bytes as f64 / 1_048_576.0,
1159 profile.memory_metrics.heap_fragmentation * 100.0
1160 ),
1161 BottleneckType::Io => format!(
1162 "IO bottleneck detected: {:.1}% IO wait time with {:.1}MB/s bandwidth. Consider async IO patterns or larger buffer sizes.",
1163 profile.io_metrics.io_wait_percent,
1164 profile.io_metrics.bandwidth_mbps
1165 ),
1166 BottleneckType::Network => format!(
1167 "Network bottleneck detected: {:.1}ms average latency with {} active connections. Consider connection pooling or request optimization.",
1168 profile.network_metrics.latency_avg_ms,
1169 profile.network_metrics.connections_active
1170 ),
1171 BottleneckType::Gpu => "GPU bottleneck detected: Consider optimizing GPU kernels or memory transfers.".to_string(),
1172 BottleneckType::Balanced => "Well-balanced resource utilization. No significant bottlenecks detected.".to_string(),
1173 BottleneckType::Unknown => "Bottleneck analysis pending - insufficient data collected.".to_string(),
1174 }
1175 }
1176
1177 fn calculate_optimization_potential(&self, scores: &ComponentScores) -> f64 {
1178 let efficiency_scores = [
1179 scores.cpu_efficiency,
1180 scores.memory_efficiency,
1181 scores.io_efficiency,
1182 scores.network_efficiency,
1183 scores.resource_balance,
1184 ];
1185
1186 let min_score = efficiency_scores
1187 .iter()
1188 .copied()
1189 .fold(f64::INFINITY, f64::min);
1190 let max_score = efficiency_scores
1191 .iter()
1192 .copied()
1193 .fold(f64::NEG_INFINITY, f64::max);
1194
1195 ((max_score - min_score) * 100.0).min(50.0) }
1198}
1199
1200impl Default for AsyncResourceMonitor {
1201 fn default() -> Self {
1202 Self::new()
1203 }
1204}
1205
1206fn current_timestamp_ms() -> u64 {
1207 use std::time::{SystemTime, UNIX_EPOCH};
1208 SystemTime::now()
1209 .duration_since(UNIX_EPOCH)
1210 .unwrap()
1211 .as_millis() as u64
1212}
1213
1214#[cfg(test)]
1215mod tests {
1216 use super::*;
1217
1218 #[test]
1219 fn test_resource_monitor_creation() {
1220 let monitor = AsyncResourceMonitor::new();
1221 assert!(monitor.profiles.is_empty());
1222 }
1223
1224 #[test]
1225 fn test_task_monitoring_lifecycle() {
1226 let mut monitor = AsyncResourceMonitor::new();
1227 let task_id = 1234;
1228
1229 monitor.start_monitoring(task_id, "test_task".to_string(), TaskType::CpuIntensive);
1230 assert!(monitor.profiles.contains_key(&task_id));
1231
1232 monitor.update_metrics(task_id);
1233 monitor.finish_monitoring(task_id);
1234
1235 let profile = monitor.get_profile(task_id).unwrap();
1236 assert!(profile.end_time.is_some());
1237 assert!(profile.duration_ms.is_some());
1238 }
1239
1240 #[test]
1241 fn test_efficiency_calculation() {
1242 let mut monitor = AsyncResourceMonitor::new();
1243 let task_id = 5678;
1244
1245 monitor.start_monitoring(task_id, "cpu_task".to_string(), TaskType::CpuIntensive);
1246 monitor.update_metrics(task_id);
1247
1248 let profile = monitor.get_profile(task_id).unwrap();
1249 assert!(profile.efficiency_score >= 0.0);
1250 assert!(profile.efficiency_score <= 1.0);
1251 assert!(profile.resource_balance >= 0.0);
1252 assert!(profile.resource_balance <= 1.0);
1253 }
1254}