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_mb = ((task_id as u64 % 50) + 1) as f64; let base_size = (base_size_mb * 1024.0 * 1024.0) as u64;
490
491 MemoryMetrics {
492 allocated_bytes: base_size + (elapsed * 512_000.0) as u64, peak_bytes: base_size + (elapsed * 768_000.0) as u64, current_bytes: base_size + (elapsed * 409_600.0) as u64, allocation_count: (elapsed * 100.0) as u64 + task_id as u64,
496 deallocation_count: (elapsed * 80.0) as u64 + task_id as u64 / 2,
497 page_faults: (elapsed * 50.0) as u64,
498 heap_fragmentation: (elapsed * 0.1).sin().abs() * 0.3,
499 memory_bandwidth_mbps: 1000.0 + (elapsed * 100.0).sin() * 200.0,
500 }
501 }
502
503 fn collect_io_metrics(&self, task_id: TaskId, task_type: &TaskType) -> IoMetrics {
504 let elapsed = self.start_time.elapsed().as_secs_f64();
505
506 let (read_multiplier, write_multiplier, latency_base) = match task_type {
507 TaskType::IoIntensive => (10.0, 5.0, 5.0),
508 TaskType::NetworkIntensive => (3.0, 3.0, 15.0),
509 TaskType::Streaming => (8.0, 2.0, 8.0),
510 TaskType::Background => (1.0, 1.0, 20.0),
511 _ => (2.0, 2.0, 10.0),
512 };
513
514 let bytes_read =
515 ((elapsed * 1_048_576.0 * read_multiplier) as u64) + (task_id as u64 * 1024);
516 let bytes_written =
517 ((elapsed * 1_048_576.0 * write_multiplier) as u64) + (task_id as u64 * 512);
518 let read_ops = bytes_read / 4096; let write_ops = bytes_written / 4096;
520
521 IoMetrics {
522 bytes_read,
523 bytes_written,
524 read_operations: read_ops,
525 write_operations: write_ops,
526 sync_operations: (read_ops + write_ops) / 3,
527 async_operations: (read_ops + write_ops) * 2 / 3,
528 avg_latency_us: latency_base + (elapsed * 0.5).sin() * 5.0,
529 bandwidth_mbps: ((bytes_read + bytes_written) as f64 / elapsed) / 1_048_576.0,
530 queue_depth: ((elapsed * 0.3).sin() * 5.0 + 5.0) as u32,
531 io_wait_percent: match task_type {
532 TaskType::IoIntensive => 25.0 + (elapsed * 0.2).sin() * 10.0,
533 _ => 5.0 + (elapsed * 0.1).sin() * 3.0,
534 },
535 }
536 }
537
538 fn collect_network_metrics(&self, task_id: TaskId, task_type: &TaskType) -> NetworkMetrics {
539 let elapsed = self.start_time.elapsed().as_secs_f64();
540
541 let (traffic_multiplier, connection_count, latency_base) = match task_type {
542 TaskType::NetworkIntensive => (5.0, 20, 10.0),
543 TaskType::Streaming => (8.0, 5, 15.0),
544 TaskType::IoIntensive => (1.0, 2, 25.0),
545 _ => (2.0, 3, 20.0),
546 };
547
548 let bytes_sent =
549 ((elapsed * 1_048_576.0 * traffic_multiplier * 0.6) as u64) + (task_id as u64 * 2048);
550 let bytes_received =
551 ((elapsed * 1_048_576.0 * traffic_multiplier * 0.4) as u64) + (task_id as u64 * 1536);
552
553 NetworkMetrics {
554 bytes_sent,
555 bytes_received,
556 packets_sent: bytes_sent / 1500, packets_received: bytes_received / 1500,
558 connections_active: connection_count + ((elapsed * 0.1).sin() * 3.0) as u32,
559 connections_established: connection_count + (elapsed * 0.1) as u32,
560 connection_errors: (elapsed * 0.05) as u32,
561 latency_avg_ms: latency_base + (elapsed * 0.3).sin() * 5.0,
562 throughput_mbps: ((bytes_sent + bytes_received) as f64 * 8.0 / elapsed) / 1_000_000.0,
563 retransmissions: (elapsed * 0.02 * traffic_multiplier) as u32,
564 }
565 }
566
567 fn collect_gpu_metrics(&self, _task_id: TaskId, task_type: &TaskType) -> Option<GpuMetrics> {
568 if !self.is_gpu_available() {
569 return None;
570 }
571
572 let elapsed = self.start_time.elapsed().as_secs_f64();
573
574 let utilization = match task_type {
575 TaskType::GpuCompute => 80.0 + (elapsed * 0.5).sin() * 15.0,
576 TaskType::Streaming => 40.0 + (elapsed * 0.3).sin() * 20.0,
577 TaskType::Mixed => 30.0 + (elapsed * 0.4).sin() * 25.0,
578 _ => 5.0 + (elapsed * 0.1).sin() * 5.0,
579 }
580 .clamp(0.0, 100.0);
581
582 Some(GpuMetrics {
583 device_name: "Simulated RTX 4090".to_string(),
584 utilization_percent: utilization,
585 memory_used_mb: utilization * 81.92, memory_total_mb: 8192.0,
587 compute_units_active: ((utilization / 100.0) * 128.0) as u32,
588 shader_operations: (elapsed * utilization * 1_000_000.0) as u64,
589 memory_bandwidth_gbps: (utilization / 100.0) * 900.0, temperature_celsius: (45.0 + (utilization / 100.0) * 35.0) as f32,
591 power_watts: (50.0 + (utilization / 100.0) * 400.0) as f32,
592 frequency_mhz: (1500.0 + (utilization / 100.0) * 800.0) as u32,
593 })
594 }
595
596 fn calculate_efficiency_score(profile: &TaskResourceProfile) -> f64 {
598 let cpu_efficiency = Self::calculate_cpu_efficiency(profile);
599 let memory_efficiency = Self::calculate_memory_efficiency(profile);
600 let io_efficiency = Self::calculate_io_efficiency(profile);
601 let network_efficiency = Self::calculate_network_efficiency(profile);
602
603 match profile.task_type {
605 TaskType::CpuIntensive => {
606 cpu_efficiency * 0.6
607 + memory_efficiency * 0.2
608 + io_efficiency * 0.1
609 + network_efficiency * 0.1
610 }
611 TaskType::IoIntensive => {
612 io_efficiency * 0.6
613 + cpu_efficiency * 0.2
614 + memory_efficiency * 0.1
615 + network_efficiency * 0.1
616 }
617 TaskType::NetworkIntensive => {
618 network_efficiency * 0.6
619 + cpu_efficiency * 0.2
620 + memory_efficiency * 0.1
621 + io_efficiency * 0.1
622 }
623 TaskType::MemoryIntensive => {
624 memory_efficiency * 0.6
625 + cpu_efficiency * 0.2
626 + io_efficiency * 0.1
627 + network_efficiency * 0.1
628 }
629 _ => (cpu_efficiency + memory_efficiency + io_efficiency + network_efficiency) / 4.0,
630 }
631 }
632
633 fn calculate_cpu_efficiency(profile: &TaskResourceProfile) -> f64 {
634 let usage = profile.cpu_metrics.usage_percent / 100.0;
635 let context_switch_penalty =
636 (profile.cpu_metrics.context_switches as f64 / 10000.0).min(0.3);
637 (usage * (1.0 - context_switch_penalty)).clamp(0.0, 1.0)
638 }
639
640 fn calculate_memory_efficiency(profile: &TaskResourceProfile) -> f64 {
641 if profile.memory_metrics.allocated_bytes == 0 {
642 return 1.0;
643 }
644 let utilization = profile.memory_metrics.current_bytes as f64
645 / profile.memory_metrics.allocated_bytes as f64;
646 let fragmentation_penalty = profile.memory_metrics.heap_fragmentation;
647 (utilization * (1.0 - fragmentation_penalty)).clamp(0.0, 1.0)
648 }
649
650 fn calculate_io_efficiency(profile: &TaskResourceProfile) -> f64 {
651 if profile.io_metrics.read_operations + profile.io_metrics.write_operations == 0 {
652 return 1.0;
653 }
654 let total_bytes = profile.io_metrics.bytes_read + profile.io_metrics.bytes_written;
655 let total_ops = profile.io_metrics.read_operations + profile.io_metrics.write_operations;
656 let avg_transfer_size = total_bytes as f64 / total_ops as f64;
657 (avg_transfer_size / 65536.0).min(1.0) }
659
660 fn calculate_network_efficiency(profile: &TaskResourceProfile) -> f64 {
661 if profile.network_metrics.connections_active == 0 {
662 return 1.0;
663 }
664 let total_bytes =
665 profile.network_metrics.bytes_sent + profile.network_metrics.bytes_received;
666 let bytes_per_connection =
667 total_bytes as f64 / profile.network_metrics.connections_active as f64;
668 let error_rate = profile.network_metrics.connection_errors as f64
669 / profile.network_metrics.connections_established.max(1) as f64;
670 let throughput_score = (bytes_per_connection / 1_048_576.0).min(1.0); throughput_score * (1.0 - error_rate)
672 }
673
674 fn calculate_resource_balance(profile: &TaskResourceProfile) -> f64 {
675 let cpu_norm = profile.cpu_metrics.usage_percent / 100.0;
676 let memory_norm = (profile.memory_metrics.current_bytes as f64 / 100_000_000.0).min(1.0);
677 let io_norm = (profile.io_metrics.bandwidth_mbps / 1000.0).min(1.0);
678 let network_norm = (profile.network_metrics.throughput_mbps / 100.0).min(1.0);
679
680 let values = [cpu_norm, memory_norm, io_norm, network_norm];
681 let mean = values.iter().sum::<f64>() / values.len() as f64;
682 let variance = values.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / values.len() as f64;
683 1.0 - variance.sqrt() }
685
686 fn identify_bottleneck(profile: &TaskResourceProfile) -> BottleneckType {
687 let cpu_pressure = profile.cpu_metrics.usage_percent / 100.0;
688 let memory_pressure =
689 (profile.memory_metrics.current_bytes as f64 / 100_000_000.0).min(1.0);
690 let io_pressure = profile.io_metrics.io_wait_percent / 100.0;
691 let network_pressure = (profile.network_metrics.latency_avg_ms / 100.0).min(1.0);
692
693 let max_pressure = cpu_pressure
694 .max(memory_pressure)
695 .max(io_pressure)
696 .max(network_pressure);
697
698 if max_pressure < 0.5 {
699 BottleneckType::Balanced
700 } else if cpu_pressure == max_pressure {
701 BottleneckType::Cpu
702 } else if memory_pressure == max_pressure {
703 BottleneckType::Memory
704 } else if io_pressure == max_pressure {
705 BottleneckType::Io
706 } else {
707 BottleneckType::Network
708 }
709 }
710
711 fn simulate_core_affinity(&self, task_type: &TaskType) -> Vec<u32> {
713 match task_type {
714 TaskType::CpuIntensive => vec![0, 1, 2, 3], TaskType::IoIntensive => vec![0], TaskType::NetworkIntensive => vec![0, 1], TaskType::GpuCompute => vec![0], _ => vec![0, 1], }
720 }
721
722 fn is_gpu_available(&self) -> bool {
723 true }
725
726 fn create_default_source_location(&self, task_name: &str) -> SourceLocation {
728 SourceLocation {
729 file_path: format!("examples/{}.rs", task_name.to_lowercase().replace(" ", "_")),
730 line_number: 42 + (task_name.len() as u32 * 3) % 100,
731 function_name: format!("execute_{}", task_name.to_lowercase().replace(" ", "_")),
732 module_path: format!(
733 "memscope_rs::examples::{}",
734 task_name.to_lowercase().replace(" ", "_")
735 ),
736 crate_name: "memscope_rs".to_string(),
737 }
738 }
739
740 fn generate_hot_metrics(&self, task_name: &str, task_type: &TaskType) -> HotMetrics {
741 let elapsed = self.start_time.elapsed().as_secs_f64();
742
743 HotMetrics {
744 cpu_hotspots: self.generate_cpu_hotspots(task_name, task_type, elapsed),
745 memory_hotspots: self.generate_memory_hotspots(task_name, task_type, elapsed),
746 io_hotspots: self.generate_io_hotspots(task_name, task_type, elapsed),
747 network_hotspots: self.generate_network_hotspots(task_name, task_type, elapsed),
748 critical_path_analysis: self
749 .generate_critical_path_analysis(task_name, task_type, elapsed),
750 }
751 }
752
753 fn generate_cpu_hotspots(
754 &self,
755 task_name: &str,
756 task_type: &TaskType,
757 elapsed: f64,
758 ) -> Vec<CpuHotspot> {
759 match task_type {
760 TaskType::CpuIntensive => vec![
761 CpuHotspot {
762 function_name: format!(
763 "{}_core_computation",
764 task_name.to_lowercase().replace(" ", "_")
765 ),
766 cpu_time_ms: elapsed * 650.0,
767 percentage_of_total: 65.0,
768 call_count: (elapsed * 1000.0) as u64,
769 avg_time_per_call: 0.65,
770 },
771 CpuHotspot {
772 function_name: "mathematical_operations".to_string(),
773 cpu_time_ms: elapsed * 200.0,
774 percentage_of_total: 20.0,
775 call_count: (elapsed * 5000.0) as u64,
776 avg_time_per_call: 0.04,
777 },
778 CpuHotspot {
779 function_name: "data_validation".to_string(),
780 cpu_time_ms: elapsed * 100.0,
781 percentage_of_total: 10.0,
782 call_count: (elapsed * 2000.0) as u64,
783 avg_time_per_call: 0.05,
784 },
785 ],
786 TaskType::IoIntensive => vec![
787 CpuHotspot {
788 function_name: "file_processing_loop".to_string(),
789 cpu_time_ms: elapsed * 150.0,
790 percentage_of_total: 35.0,
791 call_count: (elapsed * 100.0) as u64,
792 avg_time_per_call: 1.5,
793 },
794 CpuHotspot {
795 function_name: "buffer_management".to_string(),
796 cpu_time_ms: elapsed * 80.0,
797 percentage_of_total: 20.0,
798 call_count: (elapsed * 400.0) as u64,
799 avg_time_per_call: 0.2,
800 },
801 ],
802 TaskType::NetworkIntensive => vec![
803 CpuHotspot {
804 function_name: "request_serialization".to_string(),
805 cpu_time_ms: elapsed * 120.0,
806 percentage_of_total: 30.0,
807 call_count: (elapsed * 50.0) as u64,
808 avg_time_per_call: 2.4,
809 },
810 CpuHotspot {
811 function_name: "response_parsing".to_string(),
812 cpu_time_ms: elapsed * 100.0,
813 percentage_of_total: 25.0,
814 call_count: (elapsed * 45.0) as u64,
815 avg_time_per_call: 2.2,
816 },
817 ],
818 _ => vec![CpuHotspot {
819 function_name: "generic_processing".to_string(),
820 cpu_time_ms: elapsed * 200.0,
821 percentage_of_total: 40.0,
822 call_count: (elapsed * 200.0) as u64,
823 avg_time_per_call: 1.0,
824 }],
825 }
826 }
827
828 fn generate_memory_hotspots(
829 &self,
830 task_name: &str,
831 task_type: &TaskType,
832 elapsed: f64,
833 ) -> Vec<MemoryHotspot> {
834 match task_type {
835 TaskType::MemoryIntensive => vec![
836 MemoryHotspot {
837 allocation_site: format!(
838 "{}::large_buffer_allocation",
839 task_name.replace(" ", "_")
840 ),
841 bytes_allocated: (elapsed * 50_000_000.0) as u64,
842 allocation_count: (elapsed * 10.0) as u64,
843 peak_usage: (elapsed * 75_000_000.0) as u64,
844 lifetime_ms: elapsed * 800.0,
845 },
846 MemoryHotspot {
847 allocation_site: "Vec::with_capacity".to_string(),
848 bytes_allocated: (elapsed * 20_000_000.0) as u64,
849 allocation_count: (elapsed * 100.0) as u64,
850 peak_usage: (elapsed * 25_000_000.0) as u64,
851 lifetime_ms: elapsed * 300.0,
852 },
853 ],
854 TaskType::CpuIntensive => vec![MemoryHotspot {
855 allocation_site: "matrix_multiplication::allocate_result".to_string(),
856 bytes_allocated: (elapsed * 8_000_000.0) as u64,
857 allocation_count: (elapsed * 5.0) as u64,
858 peak_usage: (elapsed * 12_000_000.0) as u64,
859 lifetime_ms: elapsed * 500.0,
860 }],
861 _ => vec![MemoryHotspot {
862 allocation_site: "general_buffer".to_string(),
863 bytes_allocated: (elapsed * 5_000_000.0) as u64,
864 allocation_count: (elapsed * 20.0) as u64,
865 peak_usage: (elapsed * 7_000_000.0) as u64,
866 lifetime_ms: elapsed * 200.0,
867 }],
868 }
869 }
870
871 fn generate_io_hotspots(
872 &self,
873 task_name: &str,
874 task_type: &TaskType,
875 elapsed: f64,
876 ) -> Vec<IoHotspot> {
877 match task_type {
878 TaskType::IoIntensive => vec![
879 IoHotspot {
880 operation_type: "Sequential Read".to_string(),
881 file_path: format!(
882 "/tmp/{}_data.dat",
883 task_name.to_lowercase().replace(" ", "_")
884 ),
885 bytes_processed: (elapsed * 50_000_000.0) as u64,
886 operation_count: (elapsed * 1000.0) as u64,
887 total_time_ms: elapsed * 400.0,
888 avg_latency_ms: 0.4,
889 },
890 IoHotspot {
891 operation_type: "Random Write".to_string(),
892 file_path: format!(
893 "/tmp/{}_output.dat",
894 task_name.to_lowercase().replace(" ", "_")
895 ),
896 bytes_processed: (elapsed * 20_000_000.0) as u64,
897 operation_count: (elapsed * 500.0) as u64,
898 total_time_ms: elapsed * 200.0,
899 avg_latency_ms: 0.4,
900 },
901 ],
902 _ => vec![IoHotspot {
903 operation_type: "Config Read".to_string(),
904 file_path: "/etc/config.toml".to_string(),
905 bytes_processed: 4096,
906 operation_count: (elapsed * 2.0) as u64,
907 total_time_ms: elapsed * 10.0,
908 avg_latency_ms: 5.0,
909 }],
910 }
911 }
912
913 fn generate_network_hotspots(
914 &self,
915 task_name: &str,
916 task_type: &TaskType,
917 elapsed: f64,
918 ) -> Vec<NetworkHotspot> {
919 match task_type {
920 TaskType::NetworkIntensive => vec![
921 NetworkHotspot {
922 endpoint: "https://api.example.com/data".to_string(),
923 request_count: (elapsed * 50.0) as u64,
924 bytes_transferred: (elapsed * 5_000_000.0) as u64,
925 avg_response_time_ms: 120.0 + (elapsed * 0.1).sin() * 30.0,
926 error_rate: 0.02,
927 },
928 NetworkHotspot {
929 endpoint: "wss://stream.example.com/feed".to_string(),
930 request_count: (elapsed * 10.0) as u64,
931 bytes_transferred: (elapsed * 20_000_000.0) as u64,
932 avg_response_time_ms: 50.0 + (elapsed * 0.2).sin() * 10.0,
933 error_rate: 0.001,
934 },
935 ],
936 _ => vec![NetworkHotspot {
937 endpoint: format!("internal://{}", task_name.to_lowercase().replace(" ", "_")),
938 request_count: (elapsed * 5.0) as u64,
939 bytes_transferred: (elapsed * 100_000.0) as u64,
940 avg_response_time_ms: 25.0,
941 error_rate: 0.0,
942 }],
943 }
944 }
945
946 fn generate_critical_path_analysis(
947 &self,
948 _task_name: &str,
949 task_type: &TaskType,
950 elapsed: f64,
951 ) -> CriticalPathAnalysis {
952 let total_time = elapsed * 1000.0;
953
954 let (critical_path_ratio, parallelization_potential, blocking_ops) = match task_type {
955 TaskType::CpuIntensive => (
956 0.85,
957 0.3,
958 vec![BlockingOperation {
959 operation_name: "Memory Allocation".to_string(),
960 blocking_time_ms: total_time * 0.05,
961 frequency: (elapsed * 10.0) as u64,
962 impact_score: 0.3,
963 }],
964 ),
965 TaskType::IoIntensive => (
966 0.6,
967 0.7,
968 vec![
969 BlockingOperation {
970 operation_name: "File System Sync".to_string(),
971 blocking_time_ms: total_time * 0.25,
972 frequency: (elapsed * 20.0) as u64,
973 impact_score: 0.8,
974 },
975 BlockingOperation {
976 operation_name: "Buffer Flush".to_string(),
977 blocking_time_ms: total_time * 0.15,
978 frequency: (elapsed * 50.0) as u64,
979 impact_score: 0.5,
980 },
981 ],
982 ),
983 TaskType::NetworkIntensive => (
984 0.4,
985 0.9,
986 vec![
987 BlockingOperation {
988 operation_name: "DNS Resolution".to_string(),
989 blocking_time_ms: total_time * 0.1,
990 frequency: (elapsed * 5.0) as u64,
991 impact_score: 0.6,
992 },
993 BlockingOperation {
994 operation_name: "TCP Handshake".to_string(),
995 blocking_time_ms: total_time * 0.2,
996 frequency: (elapsed * 15.0) as u64,
997 impact_score: 0.7,
998 },
999 ],
1000 ),
1001 _ => (
1002 0.7,
1003 0.5,
1004 vec![BlockingOperation {
1005 operation_name: "Resource Contention".to_string(),
1006 blocking_time_ms: total_time * 0.1,
1007 frequency: (elapsed * 8.0) as u64,
1008 impact_score: 0.4,
1009 }],
1010 ),
1011 };
1012
1013 CriticalPathAnalysis {
1014 total_execution_time_ms: total_time,
1015 critical_path_time_ms: total_time * critical_path_ratio,
1016 parallelization_potential,
1017 blocking_operations: blocking_ops,
1018 }
1019 }
1020
1021 fn generate_initial_efficiency_explanation(&self) -> EfficiencyExplanation {
1022 EfficiencyExplanation {
1023 overall_score: 0.0,
1024 component_scores: ComponentScores {
1025 cpu_efficiency: 0.0,
1026 memory_efficiency: 0.0,
1027 io_efficiency: 0.0,
1028 network_efficiency: 0.0,
1029 resource_balance: 0.0,
1030 },
1031 recommendations: vec![PerformanceRecommendation {
1032 category: "Initialization".to_string(),
1033 description:
1034 "Task is starting up, metrics will be available after initial execution"
1035 .to_string(),
1036 impact: "Low".to_string(),
1037 difficulty: "Easy".to_string(),
1038 estimated_improvement: 0.0,
1039 }],
1040 bottleneck_analysis: "No bottlenecks detected yet - task is initializing".to_string(),
1041 optimization_potential: 0.0,
1042 }
1043 }
1044
1045 fn generate_efficiency_explanation(
1046 &self,
1047 profile: &TaskResourceProfile,
1048 ) -> EfficiencyExplanation {
1049 let cpu_eff = Self::calculate_cpu_efficiency(profile);
1050 let memory_eff = Self::calculate_memory_efficiency(profile);
1051 let io_eff = Self::calculate_io_efficiency(profile);
1052 let network_eff = Self::calculate_network_efficiency(profile);
1053
1054 let component_scores = ComponentScores {
1055 cpu_efficiency: cpu_eff,
1056 memory_efficiency: memory_eff,
1057 io_efficiency: io_eff,
1058 network_efficiency: network_eff,
1059 resource_balance: profile.resource_balance,
1060 };
1061
1062 let recommendations = self.generate_recommendations(profile, &component_scores);
1063 let bottleneck_analysis = self.generate_bottleneck_analysis(profile);
1064 let optimization_potential = self.calculate_optimization_potential(&component_scores);
1065
1066 EfficiencyExplanation {
1067 overall_score: profile.efficiency_score,
1068 component_scores,
1069 recommendations,
1070 bottleneck_analysis,
1071 optimization_potential,
1072 }
1073 }
1074
1075 fn generate_recommendations(
1076 &self,
1077 profile: &TaskResourceProfile,
1078 scores: &ComponentScores,
1079 ) -> Vec<PerformanceRecommendation> {
1080 let mut recommendations = Vec::new();
1081
1082 if scores.cpu_efficiency < 0.7 {
1084 recommendations.push(PerformanceRecommendation {
1085 category: "CPU Optimization".to_string(),
1086 description: match profile.task_type {
1087 TaskType::CpuIntensive => {
1088 "Consider vectorization, loop unrolling, or algorithm optimization"
1089 .to_string()
1090 }
1091 _ => "Reduce CPU overhead with more efficient algorithms".to_string(),
1092 },
1093 impact: "High".to_string(),
1094 difficulty: "Medium".to_string(),
1095 estimated_improvement: (0.7 - scores.cpu_efficiency) * 100.0,
1096 });
1097 }
1098
1099 if scores.memory_efficiency < 0.8 {
1101 recommendations.push(PerformanceRecommendation {
1102 category: "Memory Optimization".to_string(),
1103 description: "Optimize memory usage patterns, reduce allocations, or implement memory pooling".to_string(),
1104 impact: "Medium".to_string(),
1105 difficulty: "Medium".to_string(),
1106 estimated_improvement: (0.8 - scores.memory_efficiency) * 80.0,
1107 });
1108 }
1109
1110 if scores.io_efficiency < 0.75 && matches!(profile.task_type, TaskType::IoIntensive) {
1112 recommendations.push(PerformanceRecommendation {
1113 category: "IO Optimization".to_string(),
1114 description: "Use larger buffer sizes, implement async IO patterns, or optimize file access patterns".to_string(),
1115 impact: "High".to_string(),
1116 difficulty: "Hard".to_string(),
1117 estimated_improvement: (0.75 - scores.io_efficiency) * 120.0,
1118 });
1119 }
1120
1121 if scores.network_efficiency < 0.7
1123 && matches!(profile.task_type, TaskType::NetworkIntensive)
1124 {
1125 recommendations.push(PerformanceRecommendation {
1126 category: "Network Optimization".to_string(),
1127 description:
1128 "Implement connection pooling, request batching, or optimize serialization"
1129 .to_string(),
1130 impact: "High".to_string(),
1131 difficulty: "Medium".to_string(),
1132 estimated_improvement: (0.7 - scores.network_efficiency) * 90.0,
1133 });
1134 }
1135
1136 if scores.resource_balance < 0.6 {
1138 recommendations.push(PerformanceRecommendation {
1139 category: "Resource Balance".to_string(),
1140 description:
1141 "Balance workload across CPU, memory, and IO to avoid resource contention"
1142 .to_string(),
1143 impact: "Medium".to_string(),
1144 difficulty: "Hard".to_string(),
1145 estimated_improvement: (0.6 - scores.resource_balance) * 60.0,
1146 });
1147 }
1148
1149 recommendations
1150 }
1151
1152 fn generate_bottleneck_analysis(&self, profile: &TaskResourceProfile) -> String {
1153 match profile.bottleneck_type {
1154 BottleneckType::Cpu => format!(
1155 "CPU bottleneck detected: {:.1}% utilization. Consider optimizing computational algorithms or distributing work across multiple cores.",
1156 profile.cpu_metrics.usage_percent
1157 ),
1158 BottleneckType::Memory => format!(
1159 "Memory bottleneck detected: {:.1}MB allocated with {:.1}% fragmentation. Consider memory pooling or reducing allocation frequency.",
1160 profile.memory_metrics.current_bytes as f64 / 1_048_576.0,
1161 profile.memory_metrics.heap_fragmentation * 100.0
1162 ),
1163 BottleneckType::Io => format!(
1164 "IO bottleneck detected: {:.1}% IO wait time with {:.1}MB/s bandwidth. Consider async IO patterns or larger buffer sizes.",
1165 profile.io_metrics.io_wait_percent,
1166 profile.io_metrics.bandwidth_mbps
1167 ),
1168 BottleneckType::Network => format!(
1169 "Network bottleneck detected: {:.1}ms average latency with {} active connections. Consider connection pooling or request optimization.",
1170 profile.network_metrics.latency_avg_ms,
1171 profile.network_metrics.connections_active
1172 ),
1173 BottleneckType::Gpu => "GPU bottleneck detected: Consider optimizing GPU kernels or memory transfers.".to_string(),
1174 BottleneckType::Balanced => "Well-balanced resource utilization. No significant bottlenecks detected.".to_string(),
1175 BottleneckType::Unknown => "Bottleneck analysis pending - insufficient data collected.".to_string(),
1176 }
1177 }
1178
1179 fn calculate_optimization_potential(&self, scores: &ComponentScores) -> f64 {
1180 let efficiency_scores = [
1181 scores.cpu_efficiency,
1182 scores.memory_efficiency,
1183 scores.io_efficiency,
1184 scores.network_efficiency,
1185 scores.resource_balance,
1186 ];
1187
1188 let min_score = efficiency_scores
1189 .iter()
1190 .copied()
1191 .fold(f64::INFINITY, f64::min);
1192 let max_score = efficiency_scores
1193 .iter()
1194 .copied()
1195 .fold(f64::NEG_INFINITY, f64::max);
1196
1197 ((max_score - min_score) * 100.0).min(50.0) }
1200}
1201
1202impl Default for AsyncResourceMonitor {
1203 fn default() -> Self {
1204 Self::new()
1205 }
1206}
1207
1208fn current_timestamp_ms() -> u64 {
1209 use std::time::{SystemTime, UNIX_EPOCH};
1210 SystemTime::now()
1211 .duration_since(UNIX_EPOCH)
1212 .unwrap()
1213 .as_millis() as u64
1214}
1215
1216#[cfg(test)]
1217mod tests {
1218 use super::*;
1219
1220 #[test]
1221 fn test_resource_monitor_creation() {
1222 let monitor = AsyncResourceMonitor::new();
1223 assert!(monitor.profiles.is_empty());
1224 }
1225
1226 #[test]
1227 fn test_task_monitoring_lifecycle() {
1228 let mut monitor = AsyncResourceMonitor::new();
1229 let task_id = 1234;
1230
1231 monitor.start_monitoring(task_id, "test_task".to_string(), TaskType::CpuIntensive);
1232 assert!(monitor.profiles.contains_key(&task_id));
1233
1234 monitor.update_metrics(task_id);
1235 monitor.finish_monitoring(task_id);
1236
1237 let profile = monitor.get_profile(task_id).unwrap();
1238 assert!(profile.end_time.is_some());
1239 assert!(profile.duration_ms.is_some());
1240 }
1241
1242 #[test]
1243 fn test_efficiency_calculation() {
1244 let mut monitor = AsyncResourceMonitor::new();
1245 let task_id = 5678;
1246
1247 monitor.start_monitoring(task_id, "cpu_task".to_string(), TaskType::CpuIntensive);
1248 monitor.update_metrics(task_id);
1249
1250 let profile = monitor.get_profile(task_id).unwrap();
1251 assert!(profile.efficiency_score >= 0.0);
1252 assert!(profile.efficiency_score <= 1.0);
1253 assert!(profile.resource_balance >= 0.0);
1254 assert!(profile.resource_balance <= 1.0);
1255 }
1256}