1use super::memory_tracker::MemoryTracker;
7use crate::core::types::{
8 AllocatorStateInfo, CachePerformanceInfo, CapacityUtilization, CodeBloatLevel,
9 ContainerAnalysis, ContainerEfficiencyMetrics, ContainerType,
10 ContextType::{AsyncContext, LocalVariable},
11 CpuUsageInfo, DispatchOverhead, DynamicTypeInfo, EnhancedFragmentationAnalysis,
12 FieldLayoutInfo, GenericConstraint, GenericTypeInfo, LayoutEfficiency, MemoryLayoutInfo,
13 MemoryPressureInfo, MonomorphizationInfo, PaddingAnalysis, PerformanceImpact,
14 ReallocationPatterns, RuntimeStateInfo, TypeErasureInfo, TypeParameter, TypeRelationshipInfo,
15 TypeUsageInfo, VTableInfo,
16};
17
18impl MemoryTracker {
19 pub fn analyze_memory_layout(&self, type_name: &str, size: usize) -> Option<MemoryLayoutInfo> {
21 let alignment = self.estimate_alignment(type_name, size);
23 let field_layout = self.analyze_enhanced_field_layout(type_name, size, alignment);
24 let padding_info = self.analyze_padding(&field_layout, size, alignment);
25 let layout_efficiency = self.calculate_enhanced_layout_efficiency(
26 &field_layout,
27 &padding_info,
28 size,
29 type_name,
30 );
31
32 let container_analysis = self.analyze_container_structure(type_name, size);
34
35 Some(MemoryLayoutInfo {
36 total_size: size,
37 alignment,
38 field_layout,
39 padding_info,
40 layout_efficiency,
41 container_analysis: Some(container_analysis),
42 })
43 }
44
45 pub fn analyze_memory_fragmentation(&self) -> EnhancedFragmentationAnalysis {
47 let stats = self.stats.lock().unwrap_or_else(|e| e.into_inner());
48
49 let total_allocated = stats.total_allocated;
51 let active_memory = stats.active_memory;
52 let peak_memory = stats.peak_memory;
53
54 let fragmentation_ratio = if peak_memory > 0 {
56 1.0 - (active_memory as f64 / peak_memory as f64)
57 } else {
58 0.0
59 };
60
61 let severity = if fragmentation_ratio > 0.5 {
63 crate::core::types::FragmentationSeverity::High
64 } else if fragmentation_ratio > 0.3 {
65 crate::core::types::FragmentationSeverity::Moderate
66 } else {
67 crate::core::types::FragmentationSeverity::Low
68 };
69
70 EnhancedFragmentationAnalysis {
71 total_heap_size: total_allocated,
72 used_heap_size: active_memory,
73 free_heap_size: total_allocated.saturating_sub(active_memory),
74 free_block_count: 0, free_block_distribution: Vec::new(), fragmentation_metrics: crate::core::types::FragmentationMetrics {
77 external_fragmentation: fragmentation_ratio,
78 internal_fragmentation: 0.0, largest_free_block: 0, average_free_block_size: 0.0, severity_level: severity,
82 },
83 fragmentation_causes: Vec::new(), }
85 }
86
87 fn estimate_alignment(&self, type_name: &str, size: usize) -> usize {
89 if type_name.contains("u64") || type_name.contains("i64") || type_name.contains("f64") {
90 8
91 } else if type_name.contains("u32")
92 || type_name.contains("i32")
93 || type_name.contains("f32")
94 {
95 4
96 } else if type_name.contains("u16") || type_name.contains("i16") {
97 2
98 } else if type_name.contains("u8") || type_name.contains("i8") || type_name.contains("bool")
99 {
100 1
101 } else if type_name.contains("usize")
102 || type_name.contains("isize")
103 || type_name.contains("*")
104 {
105 std::mem::size_of::<usize>()
106 } else {
107 match size {
109 1 => 1,
110 2..=3 => 2,
111 4..=7 => 4,
112 _ => 8,
113 }
114 }
115 }
116
117 fn analyze_enhanced_field_layout(
119 &self,
120 type_name: &str,
121 total_size: usize,
122 alignment: usize,
123 ) -> Vec<FieldLayoutInfo> {
124 let mut fields = Vec::new();
125
126 if type_name.contains("Vec<") {
127 fields.push(FieldLayoutInfo {
129 field_name: "ptr".to_string(),
130 field_type: "*mut T".to_string(),
131 offset: 0,
132 size: std::mem::size_of::<usize>(),
133 alignment: std::mem::size_of::<usize>(),
134 is_padding: false,
135 });
136 fields.push(FieldLayoutInfo {
137 field_name: "capacity".to_string(),
138 field_type: "usize".to_string(),
139 offset: std::mem::size_of::<usize>(),
140 size: std::mem::size_of::<usize>(),
141 alignment: std::mem::size_of::<usize>(),
142 is_padding: false,
143 });
144 fields.push(FieldLayoutInfo {
145 field_name: "len".to_string(),
146 field_type: "usize".to_string(),
147 offset: 2 * std::mem::size_of::<usize>(),
148 size: std::mem::size_of::<usize>(),
149 alignment: std::mem::size_of::<usize>(),
150 is_padding: false,
151 });
152
153 self.analyze_vec_container_efficiency(type_name, total_size, &mut fields);
155 } else if type_name == "String" {
156 fields.push(FieldLayoutInfo {
158 field_name: "ptr".to_string(),
159 field_type: "*mut u8".to_string(),
160 offset: 0,
161 size: std::mem::size_of::<usize>(),
162 alignment: std::mem::size_of::<usize>(),
163 is_padding: false,
164 });
165 fields.push(FieldLayoutInfo {
166 field_name: "capacity".to_string(),
167 field_type: "usize".to_string(),
168 offset: std::mem::size_of::<usize>(),
169 size: std::mem::size_of::<usize>(),
170 alignment: std::mem::size_of::<usize>(),
171 is_padding: false,
172 });
173 fields.push(FieldLayoutInfo {
174 field_name: "len".to_string(),
175 field_type: "usize".to_string(),
176 offset: 2 * std::mem::size_of::<usize>(),
177 size: std::mem::size_of::<usize>(),
178 alignment: std::mem::size_of::<usize>(),
179 is_padding: false,
180 });
181
182 self.analyze_string_efficiency(total_size, &mut fields);
184 } else {
185 self.analyze_basic_field_layout(type_name, total_size, alignment, &mut fields);
187 }
188
189 fields
190 }
191
192 fn analyze_container_structure(&self, type_name: &str, size: usize) -> ContainerAnalysis {
194 let container_type = self.classify_container_type(type_name);
195 let capacity_utilization = self.analyze_capacity_utilization(&container_type, size);
196 let reallocation_patterns = self.detect_reallocation_patterns(&container_type, size);
197 let efficiency_metrics = self.calculate_container_efficiency_metrics(
198 &container_type,
199 size,
200 &capacity_utilization,
201 &reallocation_patterns,
202 );
203
204 ContainerAnalysis {
205 container_type,
206 capacity_utilization,
207 reallocation_patterns,
208 efficiency_metrics,
209 }
210 }
211
212 fn calculate_enhanced_layout_efficiency(
214 &self,
215 _fields: &[FieldLayoutInfo],
216 _padding_info: &PaddingAnalysis,
217 size: usize,
218 type_name: &str,
219 ) -> LayoutEfficiency {
220 let padding_overhead = self.calculate_padding_overhead(_fields, size);
222 let memory_utilization = self.calculate_memory_utilization(size, padding_overhead);
223
224 let container_efficiency = self.calculate_container_specific_efficiency(type_name, size);
226
227 let overall_score = (memory_utilization + container_efficiency) / 2.0;
229
230 LayoutEfficiency {
231 memory_utilization,
232 cache_friendliness: container_efficiency * 100.0, alignment_waste: padding_overhead as usize,
234 optimization_potential: if overall_score < 0.5 {
235 crate::core::types::OptimizationPotential::Major {
236 potential_savings: (padding_overhead * 0.8) as usize,
237 suggestions: self.generate_efficiency_recommendations(overall_score, type_name),
238 }
239 } else if overall_score < 0.8 {
240 crate::core::types::OptimizationPotential::Moderate {
241 potential_savings: (padding_overhead * 0.5) as usize,
242 suggestions: self.generate_efficiency_recommendations(overall_score, type_name),
243 }
244 } else {
245 crate::core::types::OptimizationPotential::None
246 },
247 }
248 }
249
250 #[allow(unused)]
252 fn analyze_padding(
253 &self,
254 fields: &[FieldLayoutInfo],
255 total_size: usize,
256 _alignment: usize,
257 ) -> PaddingAnalysis {
258 let mut total_padding = 0;
259 let mut padding_locations = Vec::new();
260
261 for i in 0..fields.len().saturating_sub(1) {
263 let current_end = fields[i].offset + fields[i].size;
264 let next_start = fields[i + 1].offset;
265 if next_start > current_end {
266 let padding_size = next_start - current_end;
267 total_padding += padding_size;
268 padding_locations.push((current_end, padding_size));
269 }
270 }
271
272 if let Some(last_field) = fields.last() {
274 let last_end = last_field.offset + last_field.size;
275 if total_size > last_end {
276 let trailing_padding = total_size - last_end;
277 total_padding += trailing_padding;
278 padding_locations.push((last_end, trailing_padding));
279 }
280 }
281
282 PaddingAnalysis {
283 total_padding_bytes: total_padding,
284 padding_locations: padding_locations
285 .into_iter()
286 .map(|(offset, size)| crate::core::types::PaddingLocation {
287 start_offset: offset,
288 size,
289 reason: crate::core::types::PaddingReason::FieldAlignment,
290 })
291 .collect(),
292 padding_ratio: if total_size > 0 {
293 total_padding as f64 / total_size as f64
294 } else {
295 0.0
296 },
297 optimization_suggestions: vec![
298 "Consider reordering fields by size (largest first)".to_string(),
299 "Use #[repr(packed)] for space-critical structs".to_string(),
300 ],
301 }
302 }
303
304 fn classify_container_type(&self, type_name: &str) -> ContainerType {
308 if type_name.contains("Vec<") {
309 ContainerType::Vec {
310 element_type: "T".to_string(), element_size: 8, }
313 } else if type_name.contains("HashMap<") {
314 ContainerType::HashMap {
315 key_type: "K".to_string(), value_type: "V".to_string(), key_size: 8, value_size: 8, }
320 } else if type_name.contains("BTreeMap<") {
321 ContainerType::BTreeMap {
322 key_type: "K".to_string(), value_type: "V".to_string(), key_size: 8, value_size: 8, }
327 } else if type_name.contains("Box<") {
328 ContainerType::Box {
329 boxed_type: "T".to_string(), boxed_size: 8, }
332 } else if type_name == "String" {
333 ContainerType::String
334 } else {
335 ContainerType::Other {
336 type_name: type_name.to_string(),
337 }
338 }
339 }
340
341 fn analyze_capacity_utilization(
343 &self,
344 container_type: &ContainerType,
345 size: usize,
346 ) -> CapacityUtilization {
347 let estimated_utilization = match container_type {
350 ContainerType::Vec { .. } | ContainerType::String => {
351 0.75
353 }
354 ContainerType::HashMap { .. } => {
355 0.75
357 }
358 ContainerType::Box { .. } => {
359 1.0
361 }
362 _ => 0.5, };
364
365 CapacityUtilization {
366 current_capacity: (size as f64 / estimated_utilization) as usize,
367 current_length: size,
368 utilization_ratio: estimated_utilization,
369 wasted_space: ((1.0 - estimated_utilization) * size as f64) as usize,
370 efficiency_assessment: if estimated_utilization > 0.9 {
371 crate::core::types::UtilizationEfficiency::Excellent
372 } else if estimated_utilization > 0.7 {
373 crate::core::types::UtilizationEfficiency::Good
374 } else if estimated_utilization > 0.5 {
375 crate::core::types::UtilizationEfficiency::Fair
376 } else {
377 crate::core::types::UtilizationEfficiency::Poor {
378 suggestion: "Consider using a more appropriate container size".to_string(),
379 }
380 },
381 }
382 }
383
384 fn detect_reallocation_patterns(
386 &self,
387 container_type: &ContainerType,
388 _size: usize,
389 ) -> ReallocationPatterns {
390 ReallocationPatterns {
393 frequency_assessment: match container_type {
394 ContainerType::Vec { .. } | ContainerType::String => {
395 crate::core::types::ReallocationFrequency::Moderate
396 }
397 ContainerType::HashMap { .. } => crate::core::types::ReallocationFrequency::Low,
398 ContainerType::Box { .. } => crate::core::types::ReallocationFrequency::None,
399 _ => crate::core::types::ReallocationFrequency::Low,
400 },
401 growth_pattern: crate::core::types::GrowthPattern::Exponential,
402 estimated_reallocations: 2, optimization_suggestions: vec![
404 "Consider pre-allocating capacity if size is known".to_string()
405 ],
406 }
407 }
408
409 fn calculate_container_efficiency_metrics(
411 &self,
412 container_type: &ContainerType,
413 _size: usize,
414 capacity_utilization: &CapacityUtilization,
415 _reallocation_patterns: &ReallocationPatterns,
416 ) -> ContainerEfficiencyMetrics {
417 let access_efficiency = match container_type {
418 ContainerType::Vec { .. } | ContainerType::String => 0.95, ContainerType::HashMap { .. } => 0.85, ContainerType::BTreeMap { .. } => 0.75, ContainerType::Box { .. } => 1.0, _ => 0.5,
423 };
424
425 let memory_overhead = match container_type {
426 ContainerType::Vec { .. } | ContainerType::String => 0.1, ContainerType::HashMap { .. } => 0.25, ContainerType::BTreeMap { .. } => 0.15, ContainerType::Box { .. } => 0.05, _ => 0.2,
431 };
432
433 ContainerEfficiencyMetrics {
434 memory_overhead,
435 cache_efficiency: access_efficiency * 100.0,
436 access_efficiency: crate::core::types::AccessEfficiency::Sequential, health_score: (access_efficiency
438 + capacity_utilization.utilization_ratio
439 + (1.0 - memory_overhead))
440 / 3.0
441 * 100.0,
442 }
443 }
444
445 fn analyze_vec_container_efficiency(
448 &self,
449 type_name: &str,
450 total_size: usize,
451 fields: &mut Vec<FieldLayoutInfo>,
452 ) {
453 let element_type = if let Some(start) = type_name.find('<') {
455 if let Some(end) = type_name.rfind('>') {
456 &type_name[start + 1..end]
457 } else {
458 "T"
459 }
460 } else {
461 "T"
462 };
463
464 let element_size = self.estimate_type_size(element_type);
466
467 fields.push(FieldLayoutInfo {
469 field_name: "efficiency_analysis".to_string(),
470 field_type: format!("VecEfficiency<{element_type}>"),
471 offset: 0, size: 0, alignment: 1,
474 is_padding: false,
475 });
476
477 let estimated_capacity = if total_size > 24 {
479 (total_size - 24) / element_size.max(1)
481 } else {
482 0
483 };
484
485 if estimated_capacity > 0 {
486 fields.push(FieldLayoutInfo {
487 field_name: "capacity_analysis".to_string(),
488 field_type: format!("EstimatedCapacity: {estimated_capacity}"),
489 offset: 0, size: 0, alignment: 1,
492 is_padding: false,
493 });
494 }
495 }
496
497 fn analyze_string_efficiency(&self, total_size: usize, fields: &mut Vec<FieldLayoutInfo>) {
498 let estimated_capacity = total_size.saturating_sub(24);
500
501 fields.push(FieldLayoutInfo {
502 field_name: "string_analysis".to_string(),
503 field_type: format!("StringCapacity: {estimated_capacity} bytes"),
504 offset: 0, size: 0, alignment: 1,
507 is_padding: false,
508 });
509
510 fields.push(FieldLayoutInfo {
512 field_name: "encoding_info".to_string(),
513 field_type: "UTF-8 encoded".to_string(),
514 offset: 0, size: 0, alignment: 1,
517 is_padding: false,
518 });
519 }
520
521 fn analyze_basic_field_layout(
522 &self,
523 type_name: &str,
524 total_size: usize,
525 alignment: usize,
526 fields: &mut Vec<FieldLayoutInfo>,
527 ) {
528 fields.push(FieldLayoutInfo {
530 field_name: "data".to_string(),
531 field_type: type_name.to_string(),
532 offset: 0,
533 size: total_size,
534 alignment,
535 is_padding: false,
536 });
537
538 let aligned_size = (total_size + alignment - 1) & !(alignment - 1);
540 if aligned_size > total_size {
541 fields.push(FieldLayoutInfo {
542 field_name: "tail_padding".to_string(),
543 field_type: "padding".to_string(),
544 offset: total_size,
545 size: aligned_size - total_size,
546 alignment: 1,
547 is_padding: true,
548 });
549 }
550 }
551
552 fn calculate_padding_overhead(&self, fields: &[FieldLayoutInfo], size: usize) -> f64 {
553 let total_padding: usize = fields
554 .iter()
555 .filter(|field| field.is_padding)
556 .map(|field| field.size)
557 .sum();
558
559 if size > 0 {
560 total_padding as f64 / size as f64
561 } else {
562 0.0
563 }
564 }
565
566 fn calculate_memory_utilization(&self, size: usize, padding_overhead: f64) -> f64 {
567 if size > 0 {
568 1.0 - padding_overhead
569 } else {
570 0.0
571 }
572 }
573
574 fn calculate_container_specific_efficiency(&self, type_name: &str, size: usize) -> f64 {
575 match type_name {
576 name if name.contains("Vec<") => {
577 if size > 24 {
579 0.85 } else {
581 0.6 }
583 }
584 name if name.contains("HashMap<") => {
585 if size > 48 {
587 0.75 } else {
589 0.5 }
591 }
592 name if name.contains("Box<") => 1.0, "String" => {
594 if size > 24 {
595 0.9 } else {
597 0.7 }
599 }
600 _ => 0.8, }
602 }
603
604 fn generate_efficiency_recommendations(&self, score: f64, type_name: &str) -> Vec<String> {
605 let mut recommendations = Vec::new();
606
607 if score < 0.5 {
608 recommendations.push(
609 "Consider significant restructuring for better memory efficiency".to_string(),
610 );
611 }
612
613 if type_name.contains("Vec<") {
614 if score < 0.8 {
615 recommendations.push(
616 "Consider pre-allocating Vec capacity with Vec::with_capacity()".to_string(),
617 );
618 recommendations
619 .push("Use Vec::shrink_to_fit() to reduce unused capacity".to_string());
620 }
621 } else if type_name.contains("HashMap<") {
622 if score < 0.7 {
623 recommendations
624 .push("Consider pre-sizing HashMap with HashMap::with_capacity()".to_string());
625 recommendations.push(
626 "Evaluate if BTreeMap might be more efficient for your use case".to_string(),
627 );
628 }
629 } else if type_name == "String" && score < 0.8 {
630 recommendations
631 .push("Consider using String::with_capacity() for known string sizes".to_string());
632 recommendations.push("Use &str instead of String when possible".to_string());
633 }
634
635 if score < 0.6 {
636 recommendations
637 .push("Consider using #[repr(packed)] for space-critical structs".to_string());
638 recommendations.push(
639 "Reorder struct fields by size (largest first) to minimize padding".to_string(),
640 );
641 }
642
643 if recommendations.is_empty() {
644 recommendations.push("Memory layout is already well optimized".to_string());
645 }
646
647 recommendations
648 }
649
650 pub(crate) fn estimate_type_size(&self, type_name: &str) -> usize {
652 match type_name {
653 "u8" | "i8" | "bool" => 1,
654 "u16" | "i16" => 2,
655 "u32" | "i32" | "f32" => 4,
656 "u64" | "i64" | "f64" => 8,
657 "usize" | "isize" => std::mem::size_of::<usize>(),
658 "String" => 24, name if name.starts_with("Vec<") => 24,
660 name if name.starts_with("HashMap<") => 48,
661 name if name.starts_with("Box<") => std::mem::size_of::<usize>(),
662 _ => 8, }
664 }
665
666 pub fn analyze_generic_type(&self, type_name: &str, size: usize) -> Option<GenericTypeInfo> {
668 if !type_name.contains('<') || !type_name.contains('>') {
669 return None; }
671
672 let base_type = self.extract_base_type(type_name);
673 let type_parameters = self.extract_type_parameters(type_name, size);
674 let monomorphization_info = self.analyze_monomorphization(&base_type, &type_parameters);
675 let constraints = self.infer_generic_constraints(&base_type, &type_parameters);
676
677 Some(GenericTypeInfo {
678 base_type,
679 type_parameters,
680 monomorphization_info,
681 constraints,
682 })
683 }
684
685 pub fn analyze_dynamic_type(&self, type_name: &str, size: usize) -> Option<DynamicTypeInfo> {
687 if !type_name.contains("dyn ") && !type_name.contains("Box<dyn") {
688 return None; }
690
691 let trait_name = self.extract_trait_name(type_name);
692 let vtable_info = self.analyze_vtable(&trait_name, size);
693 let concrete_type = self.try_infer_concrete_type(type_name);
694 let dispatch_overhead = self.calculate_dispatch_overhead(&trait_name);
695 let type_erasure_info = self.analyze_type_erasure(size);
696
697 Some(DynamicTypeInfo {
698 trait_name,
699 vtable_info,
700 concrete_type,
701 dispatch_overhead,
702 type_erasure_info,
703 })
704 }
705
706 pub fn collect_runtime_state(&self) -> RuntimeStateInfo {
708 RuntimeStateInfo {
709 cpu_usage: self.collect_cpu_usage(),
710 memory_pressure: self.assess_memory_pressure(),
711 cache_performance: self.estimate_cache_performance(),
712 allocator_state: self.analyze_allocator_state(),
713 gc_info: None, }
715 }
716
717 fn extract_base_type(&self, type_name: &str) -> String {
718 if let Some(pos) = type_name.find('<') {
719 type_name[..pos].to_string()
720 } else {
721 type_name.to_string()
722 }
723 }
724
725 fn extract_trait_name(&self, type_name: &str) -> String {
726 if type_name.contains("dyn ") {
727 if let Some(start) = type_name.find("dyn ") {
728 let after_dyn = &type_name[start + 4..];
729 if let Some(end) = after_dyn.find('>') {
730 after_dyn[..end].trim().to_string()
731 } else {
732 after_dyn.trim().to_string()
733 }
734 } else {
735 "Unknown".to_string()
736 }
737 } else {
738 "Unknown".to_string()
739 }
740 }
741
742 fn collect_cpu_usage(&self) -> CpuUsageInfo {
744 CpuUsageInfo {
746 current_usage_percent: 15.0, average_usage_percent: 12.0,
748 peak_usage_percent: 25.0,
749 intensive_operations_count: 100,
750 }
751 }
752
753 fn assess_memory_pressure(&self) -> MemoryPressureInfo {
755 let stats = self.stats.lock().unwrap_or_else(|e| e.into_inner());
756 let pressure_level = if stats.active_memory > 1024 * 1024 * 100 {
757 crate::core::types::MemoryPressureLevel::High
759 } else if stats.active_memory > 1024 * 1024 * 50 {
760 crate::core::types::MemoryPressureLevel::Moderate
762 } else {
763 crate::core::types::MemoryPressureLevel::Low
764 };
765
766 MemoryPressureInfo {
767 pressure_level,
768 available_memory_percent: 75.0, allocation_failures: 0,
770 fragmentation_level: stats.fragmentation_analysis.fragmentation_ratio,
771 }
772 }
773
774 fn estimate_cache_performance(&self) -> CachePerformanceInfo {
776 CachePerformanceInfo {
777 l1_hit_rate: 0.95,
778 l2_hit_rate: 0.85,
779 l3_hit_rate: 0.70,
780 cache_miss_penalty_ns: 100.0,
781 access_pattern: crate::core::types::MemoryAccessPattern::Mixed,
782 }
783 }
784
785 pub fn analyze_type_relationships(&self, type_name: &str) -> Option<TypeRelationshipInfo> {
787 Some(TypeRelationshipInfo {
788 type_name: type_name.to_string(),
789 parent_types: vec![],
790 child_types: vec![],
791 composed_types: vec![],
792 complexity_score: self.calculate_type_complexity(type_name),
793 inheritance_depth: 0,
794 composition_breadth: 0,
795 })
796 }
797
798 fn calculate_type_complexity(&self, type_name: &str) -> u32 {
800 let mut score = 1;
801 if type_name.contains('<') {
802 score += 2;
803 }
804 if type_name.contains("dyn") {
805 score += 3;
806 }
807 if type_name.contains("impl") {
808 score += 2;
809 }
810 score += type_name.matches(',').count() as u32;
811 score
812 }
813
814 pub fn track_type_usage(&self, type_name: &str) -> Option<TypeUsageInfo> {
816 let active_allocations = match self.get_active_allocations() {
818 Ok(allocations) => allocations,
819 Err(_) => return None, };
821
822 let mut type_count = 0u64;
824 let mut total_size = 0usize;
825 let mut allocation_timestamps = Vec::new();
826 let mut allocation_sizes = Vec::new();
827
828 for allocation in &active_allocations {
830 if let Some(ref alloc_type) = allocation.type_name {
831 if alloc_type == type_name {
832 type_count += 1;
833 total_size += allocation.size;
834 allocation_timestamps.push(allocation.timestamp_alloc);
835 allocation_sizes.push(allocation.size);
836 }
837 }
838 }
839
840 if type_count == 0 {
842 return Some(TypeUsageInfo {
843 type_name: type_name.to_string(),
844 total_usage_count: 1,
845 usage_contexts: vec![],
846 usage_timeline: vec![],
847 hot_paths: vec![],
848 performance_impact: self.calculate_basic_performance_impact(type_name),
849 });
850 }
851
852 let usage_timeline = self.create_usage_timeline(&allocation_timestamps, &allocation_sizes);
854
855 let usage_contexts = self.analyze_usage_contexts(type_name, type_count, total_size);
857
858 let performance_impact = self.calculate_type_performance_impact(
860 type_name,
861 type_count,
862 total_size,
863 &allocation_sizes,
864 );
865
866 Some(TypeUsageInfo {
867 type_name: type_name.to_string(),
868 total_usage_count: type_count,
869 usage_contexts,
870 usage_timeline,
871 hot_paths: vec![], performance_impact,
873 })
874 }
875
876 fn generate_optimization_recommendations(
878 &self,
879 type_name: &str,
880 ) -> Vec<crate::core::types::OptimizationRecommendation> {
881 let mut recommendations = Vec::new();
882
883 match type_name {
884 "String" => {
885 recommendations.push(crate::core::types::OptimizationRecommendation {
886 recommendation_type:
887 crate::core::types::RecommendationType::DataStructureChange,
888 priority: crate::core::types::Priority::Medium,
889 description: "Consider using &str when possible to avoid allocations"
890 .to_string(),
891 expected_improvement: 15.0,
892 implementation_difficulty: crate::core::types::ImplementationDifficulty::Easy,
893 });
894 recommendations.push(crate::core::types::OptimizationRecommendation {
895 recommendation_type: crate::core::types::RecommendationType::MemoryLayout,
896 priority: crate::core::types::Priority::Medium,
897 description: "Use String::with_capacity() when final size is known".to_string(),
898 expected_improvement: 20.0,
899 implementation_difficulty: crate::core::types::ImplementationDifficulty::Easy,
900 });
901 }
902 name if name.starts_with("Vec<") => {
903 recommendations.push(crate::core::types::OptimizationRecommendation {
904 recommendation_type: crate::core::types::RecommendationType::MemoryLayout,
905 priority: crate::core::types::Priority::High,
906 description: "Use Vec::with_capacity() when size is predictable".to_string(),
907 expected_improvement: 25.0,
908 implementation_difficulty: crate::core::types::ImplementationDifficulty::Easy,
909 });
910 recommendations.push(crate::core::types::OptimizationRecommendation {
911 recommendation_type:
912 crate::core::types::RecommendationType::DataStructureChange,
913 priority: crate::core::types::Priority::Low,
914 description: "Consider using SmallVec for small collections".to_string(),
915 expected_improvement: 10.0,
916 implementation_difficulty: crate::core::types::ImplementationDifficulty::Medium,
917 });
918 }
919 name if name.starts_with("HashMap<") => {
920 recommendations.push(crate::core::types::OptimizationRecommendation {
921 recommendation_type: crate::core::types::RecommendationType::MemoryLayout,
922 priority: crate::core::types::Priority::High,
923 description: "Use HashMap::with_capacity() for better performance".to_string(),
924 expected_improvement: 30.0,
925 implementation_difficulty: crate::core::types::ImplementationDifficulty::Easy,
926 });
927 recommendations.push(crate::core::types::OptimizationRecommendation {
928 recommendation_type:
929 crate::core::types::RecommendationType::DataStructureChange,
930 priority: crate::core::types::Priority::Medium,
931 description:
932 "Consider using FxHashMap for better performance with integer keys"
933 .to_string(),
934 expected_improvement: 15.0,
935 implementation_difficulty: crate::core::types::ImplementationDifficulty::Medium,
936 });
937 }
938 name if name.starts_with("Box<") => {
939 recommendations.push(crate::core::types::OptimizationRecommendation {
940 recommendation_type: crate::core::types::RecommendationType::MemoryLayout,
941 priority: crate::core::types::Priority::Low,
942 description: "Box is efficient for heap allocation of single values"
943 .to_string(),
944 expected_improvement: 5.0,
945 implementation_difficulty: crate::core::types::ImplementationDifficulty::Easy,
946 });
947 }
948 name if name.starts_with("Rc<") => {
949 recommendations.push(crate::core::types::OptimizationRecommendation {
950 recommendation_type:
951 crate::core::types::RecommendationType::DataStructureChange,
952 priority: crate::core::types::Priority::Medium,
953 description: "Consider Arc<> for thread-safe reference counting".to_string(),
954 expected_improvement: 0.0, implementation_difficulty: crate::core::types::ImplementationDifficulty::Easy,
956 });
957 recommendations.push(crate::core::types::OptimizationRecommendation {
958 recommendation_type: crate::core::types::RecommendationType::MemoryLayout,
959 priority: crate::core::types::Priority::High,
960 description: "Be aware of potential reference cycles".to_string(),
961 expected_improvement: 0.0, implementation_difficulty: crate::core::types::ImplementationDifficulty::Medium,
963 });
964 }
965 name if name.starts_with("Arc<") => {
966 recommendations.push(crate::core::types::OptimizationRecommendation {
967 recommendation_type:
968 crate::core::types::RecommendationType::DataStructureChange,
969 priority: crate::core::types::Priority::Low,
970 description: "Arc has atomic overhead - use Rc if single-threaded".to_string(),
971 expected_improvement: 10.0,
972 implementation_difficulty: crate::core::types::ImplementationDifficulty::Easy,
973 });
974 recommendations.push(crate::core::types::OptimizationRecommendation {
975 recommendation_type: crate::core::types::RecommendationType::MemoryLayout,
976 priority: crate::core::types::Priority::Medium,
977 description: "Consider weak references to break cycles".to_string(),
978 expected_improvement: 0.0, implementation_difficulty: crate::core::types::ImplementationDifficulty::Medium,
980 });
981 }
982 _ => {
983 recommendations.push(crate::core::types::OptimizationRecommendation {
984 recommendation_type: crate::core::types::RecommendationType::MemoryLayout,
985 priority: crate::core::types::Priority::Low,
986 description: "Consider the memory layout and access patterns".to_string(),
987 expected_improvement: 5.0,
988 implementation_difficulty: crate::core::types::ImplementationDifficulty::Medium,
989 });
990 }
991 }
992
993 recommendations
994 }
995
996 fn calculate_type_performance_impact(
999 &self,
1000 type_name: &str,
1001 usage_count: u64,
1002 total_size: usize,
1003 allocation_sizes: &[usize],
1004 ) -> crate::core::types::TypePerformanceImpact {
1005 let avg_size = if usage_count > 0 {
1006 total_size as f64 / usage_count as f64
1007 } else {
1008 0.0
1009 };
1010
1011 let size_variance = if allocation_sizes.len() > 1 {
1013 let mean = avg_size;
1014 let variance = allocation_sizes
1015 .iter()
1016 .map(|&size| (size as f64 - mean).powi(2))
1017 .sum::<f64>()
1018 / allocation_sizes.len() as f64;
1019 variance.sqrt()
1020 } else {
1021 0.0
1022 };
1023
1024 let mut base_scores = self.calculate_basic_performance_impact(type_name);
1026
1027 if usage_count > 1000 {
1031 base_scores.performance_score *= 0.9; base_scores.cpu_efficiency_score *= 0.95;
1033 }
1034
1035 if avg_size > 1024.0 * 1024.0 {
1037 base_scores.memory_efficiency_score *= 0.8;
1039 base_scores.cache_efficiency_score *= 0.7;
1040 }
1041
1042 if size_variance > avg_size * 0.5 {
1044 base_scores.memory_efficiency_score *= 0.9;
1045 }
1046
1047 let mut recommendations = base_scores.optimization_recommendations;
1049
1050 if usage_count > 100 && avg_size < 64.0 {
1051 recommendations.push(crate::core::types::OptimizationRecommendation {
1052 recommendation_type: crate::core::types::RecommendationType::MemoryPooling,
1053 priority: crate::core::types::Priority::High,
1054 description:
1055 "Consider using object pooling for small, frequently allocated objects"
1056 .to_string(),
1057 expected_improvement: 25.0,
1058 implementation_difficulty: crate::core::types::ImplementationDifficulty::Medium,
1059 });
1060 }
1061
1062 if size_variance > avg_size {
1063 recommendations.push(crate::core::types::OptimizationRecommendation {
1064 recommendation_type: crate::core::types::RecommendationType::MemoryLayout,
1065 priority: crate::core::types::Priority::High,
1066 description:
1067 "Consider pre-allocating with estimated capacity to reduce reallocations"
1068 .to_string(),
1069 expected_improvement: 30.0,
1070 implementation_difficulty: crate::core::types::ImplementationDifficulty::Easy,
1071 });
1072 }
1073
1074 if total_size > 10 * 1024 * 1024 {
1075 recommendations.push(crate::core::types::OptimizationRecommendation {
1077 recommendation_type: crate::core::types::RecommendationType::MemoryLayout,
1078 priority: crate::core::types::Priority::Critical,
1079 description:
1080 "Consider memory usage optimization - this type uses significant memory"
1081 .to_string(),
1082 expected_improvement: 40.0,
1083 implementation_difficulty: crate::core::types::ImplementationDifficulty::Hard,
1084 });
1085 }
1086
1087 crate::core::types::TypePerformanceImpact {
1088 performance_score: base_scores.performance_score,
1089 memory_efficiency_score: base_scores.memory_efficiency_score,
1090 cpu_efficiency_score: base_scores.cpu_efficiency_score,
1091 cache_efficiency_score: base_scores.cache_efficiency_score,
1092 optimization_recommendations: recommendations,
1093 }
1094 }
1095
1096 fn calculate_basic_performance_impact(
1098 &self,
1099 type_name: &str,
1100 ) -> crate::core::types::TypePerformanceImpact {
1101 let (perf_score, mem_score, cpu_score, cache_score) = match type_name {
1103 "String" => (80.0, 85.0, 90.0, 75.0),
1104 name if name.starts_with("Vec<") => (85.0, 90.0, 85.0, 80.0),
1105 name if name.starts_with("HashMap<") => (75.0, 80.0, 70.0, 65.0),
1106 name if name.starts_with("Box<") => (90.0, 95.0, 95.0, 90.0),
1107 name if name.starts_with("Rc<") || name.starts_with("Arc<") => (85.0, 85.0, 80.0, 85.0),
1108 _ => (85.0, 90.0, 80.0, 75.0), };
1110
1111 crate::core::types::TypePerformanceImpact {
1112 performance_score: perf_score,
1113 memory_efficiency_score: mem_score,
1114 cpu_efficiency_score: cpu_score,
1115 cache_efficiency_score: cache_score,
1116 optimization_recommendations: self.generate_optimization_recommendations(type_name),
1117 }
1118 }
1119
1120 fn create_usage_timeline(
1122 &self,
1123 timestamps: &[u64],
1124 sizes: &[usize],
1125 ) -> Vec<crate::core::types::UsageTimePoint> {
1126 if timestamps.is_empty() {
1127 return vec![];
1128 }
1129
1130 let mut timeline = Vec::new();
1132 let window_size_ns = 1_000_000_000; if let (Some(&first_ts), Some(&last_ts)) = (timestamps.first(), timestamps.last()) {
1135 let mut current_window = first_ts;
1136
1137 while current_window <= last_ts {
1138 let window_end = current_window + window_size_ns;
1139
1140 let mut usage_count = 0u32;
1142 let mut memory_usage = 0usize;
1143
1144 for (i, &ts) in timestamps.iter().enumerate() {
1145 if ts >= current_window && ts < window_end {
1146 usage_count += 1;
1147 memory_usage += sizes[i];
1148 }
1149 }
1150
1151 if usage_count > 0 {
1152 timeline.push(crate::core::types::UsageTimePoint {
1153 timestamp: current_window,
1154 usage_count,
1155 memory_usage,
1156 performance_snapshot: crate::core::types::PerformanceSnapshot {
1157 cpu_usage: 0.0, memory_usage: memory_usage as f64,
1159 cache_hit_rate: 0.95, throughput: usage_count as f64,
1161 },
1162 });
1163 }
1164
1165 current_window = window_end;
1166 }
1167 }
1168
1169 timeline
1170 }
1171
1172 fn analyze_usage_contexts(
1174 &self,
1175 type_name: &str,
1176 usage_count: u64,
1177 total_size: usize,
1178 ) -> Vec<crate::core::types::UsageContext> {
1179 let mut contexts = Vec::new();
1180
1181 let context_type = if type_name.starts_with("Vec<")
1183 || type_name.starts_with("HashMap<")
1184 || type_name.starts_with("BTreeMap<")
1185 || type_name.starts_with("Box<")
1186 || type_name.starts_with("Rc<")
1187 || type_name.starts_with("Arc<")
1188 || type_name == "String"
1189 || type_name.starts_with("&str")
1190 {
1191 LocalVariable
1192 } else if type_name.contains("Future") || type_name.contains("async") {
1193 AsyncContext
1194 } else {
1195 LocalVariable
1196 };
1197
1198 let avg_size = if usage_count > 0 {
1200 total_size as f64 / usage_count as f64
1201 } else {
1202 0.0
1203 };
1204 let allocation_frequency = usage_count as f64; contexts.push(crate::core::types::UsageContext {
1207 context_type,
1208 location: "unknown".to_string(), frequency: usage_count as u32,
1210 performance_metrics: crate::core::types::ContextPerformanceMetrics {
1211 avg_execution_time_ns: avg_size * 10.0, allocation_frequency,
1213 cache_miss_rate: self.estimate_cache_miss_rate(type_name, avg_size),
1214 branch_misprediction_rate: 0.05, },
1216 });
1217
1218 contexts
1219 }
1220
1221 fn estimate_cache_miss_rate(&self, type_name: &str, avg_size: f64) -> f64 {
1223 let cache_line_size = 64.0;
1225
1226 if avg_size <= cache_line_size {
1227 0.05 } else if avg_size <= cache_line_size * 4.0 {
1229 0.15 } else if type_name.starts_with("Vec<") || type_name.starts_with("HashMap<") {
1231 0.25 } else {
1233 0.35 }
1235 }
1236
1237 pub fn analyze_stack_allocation(
1239 &self,
1240 type_name: &str,
1241 ptr: usize,
1242 ) -> Option<crate::core::types::StackAllocationInfo> {
1243 let stack_start = 0x7fff_0000_0000; let stack_end = 0x7fff_ffff_ffff; if ptr >= stack_start && ptr <= stack_end {
1248 Some(crate::core::types::StackAllocationInfo {
1249 frame_id: (ptr >> 12) & 0xffff, var_name: "stack_var".to_string(),
1251 stack_offset: (ptr as isize) - (stack_start as isize),
1252 size: self.estimate_type_size(type_name),
1253 function_name: "unknown_function".to_string(),
1254 stack_depth: self.estimate_stack_depth(ptr),
1255 scope_info: crate::core::types::StackScopeInfo {
1256 scope_type: crate::core::types::ScopeType::Function,
1257 start_line: None,
1258 end_line: None,
1259 parent_scope: None,
1260 nesting_level: 1,
1261 },
1262 })
1263 } else {
1264 None
1265 }
1266 }
1267
1268 fn estimate_stack_depth(&self, ptr: usize) -> usize {
1270 let stack_start = 0x7fff_0000_0000;
1271 if ptr >= stack_start {
1272 ((ptr - stack_start) / 4096).min(100) } else {
1274 0
1275 }
1276 }
1277
1278 fn extract_type_parameters(&self, type_name: &str, total_size: usize) -> Vec<TypeParameter> {
1280 let mut parameters = Vec::new();
1281
1282 if let Some(start) = type_name.find('<') {
1283 if let Some(end) = type_name.rfind('>') {
1284 let params_str = &type_name[start + 1..end];
1285 let param_names: Vec<&str> = params_str.split(',').map(|s| s.trim()).collect();
1286
1287 for (i, param_name) in param_names.iter().enumerate() {
1288 let estimated_size = self.estimate_type_parameter_size(
1289 param_name,
1290 total_size,
1291 param_names.len(),
1292 );
1293 parameters.push(TypeParameter {
1294 name: format!("T{i}"),
1295 concrete_type: param_name.to_string(),
1296 size: estimated_size,
1297 alignment: self.estimate_alignment(param_name, estimated_size),
1298 is_lifetime: param_name.starts_with('\''),
1299 });
1300 }
1301 }
1302 }
1303
1304 parameters
1305 }
1306
1307 fn analyze_vtable(&self, trait_name: &str, _size: usize) -> VTableInfo {
1309 let method_count = match trait_name {
1310 "Display" | "Debug" => 1,
1311 "Iterator" => 2,
1312 "Clone" => 1,
1313 "Drop" => 1,
1314 _ => 3, };
1316
1317 let vtable_size =
1318 method_count * std::mem::size_of::<usize>() + std::mem::size_of::<usize>(); let methods = (0..method_count)
1320 .map(|i| crate::core::types::VTableMethod {
1321 name: format!("method_{i}"),
1322 signature: "fn(&self) -> ()".to_string(),
1323 vtable_offset: i * std::mem::size_of::<usize>(),
1324 })
1325 .collect();
1326
1327 VTableInfo {
1328 vtable_size,
1329 method_count,
1330 vtable_ptr_offset: 0,
1331 methods,
1332 }
1333 }
1334
1335 fn try_infer_concrete_type(&self, type_name: &str) -> Option<String> {
1337 if type_name.contains("String") {
1339 Some("String".to_string())
1340 } else if type_name.contains("Vec") {
1341 Some("Vec<T>".to_string())
1342 } else {
1343 None
1344 }
1345 }
1346
1347 fn calculate_dispatch_overhead(&self, trait_name: &str) -> DispatchOverhead {
1349 let indirect_call_overhead_ns = match trait_name {
1350 "Display" | "Debug" => 2.0, "Iterator" => 3.0,
1352 _ => 5.0, };
1354
1355 DispatchOverhead {
1356 indirect_call_overhead_ns,
1357 cache_miss_probability: 0.1, branch_misprediction_rate: 0.05, performance_impact: if indirect_call_overhead_ns > 4.0 {
1360 PerformanceImpact::Moderate
1361 } else {
1362 PerformanceImpact::Minor
1363 },
1364 }
1365 }
1366
1367 fn analyze_type_erasure(&self, size: usize) -> TypeErasureInfo {
1369 TypeErasureInfo {
1370 type_info_recoverable: false, size_info: Some(size),
1372 alignment_info: Some(std::mem::size_of::<usize>()), destructor_info: Some("dynamic".to_string()),
1374 }
1375 }
1376
1377 fn analyze_monomorphization(
1379 &self,
1380 _base_type: &str,
1381 parameters: &[TypeParameter],
1382 ) -> MonomorphizationInfo {
1383 let instance_count = parameters
1385 .iter()
1386 .map(|p| if p.concrete_type.contains('<') { 2 } else { 1 })
1387 .product::<usize>()
1388 .max(1);
1389
1390 let per_instance_memory = parameters.iter().map(|p| p.size).sum::<usize>();
1391 let total_memory_usage = instance_count * per_instance_memory;
1392
1393 let code_bloat_assessment = match instance_count {
1394 1..=2 => CodeBloatLevel::Low,
1395 3..=5 => CodeBloatLevel::Moderate,
1396 6..=10 => CodeBloatLevel::High,
1397 _ => CodeBloatLevel::Excessive,
1398 };
1399
1400 MonomorphizationInfo {
1401 instance_count,
1402 per_instance_memory,
1403 total_memory_usage,
1404 code_bloat_assessment,
1405 }
1406 }
1407
1408 fn infer_generic_constraints(
1410 &self,
1411 _base_type: &str,
1412 _parameters: &[TypeParameter],
1413 ) -> Vec<GenericConstraint> {
1414 let mut constraints = Vec::new();
1415
1416 match _base_type {
1417 "Vec" | "HashMap" | "BTreeMap" => {
1418 constraints.push(GenericConstraint {
1419 constraint_type: crate::core::types::ConstraintType::Trait("Clone".to_string()),
1420 description: "Element types typically need to implement Clone".to_string(),
1421 memory_impact: crate::core::types::MemoryImpact::None,
1422 });
1423 }
1424 "Rc" | "Arc" => {
1425 constraints.push(GenericConstraint {
1426 constraint_type: crate::core::types::ConstraintType::Trait(
1427 "Send + Sync".to_string(),
1428 ),
1429 description: "Shared pointer contents need to be thread-safe".to_string(),
1430 memory_impact: crate::core::types::MemoryImpact::SizeIncrease(
1431 std::mem::size_of::<usize>(),
1432 ),
1433 });
1434 }
1435 _ => {}
1436 }
1437
1438 constraints
1439 }
1440
1441 fn analyze_allocator_state(&self) -> AllocatorStateInfo {
1443 let stats = self.stats.lock().unwrap_or_else(|e| e.into_inner());
1444
1445 AllocatorStateInfo {
1446 allocator_type: "System".to_string(),
1447 heap_size: 1024 * 1024 * 1024, heap_used: stats.active_memory,
1449 free_blocks_count: 1000, largest_free_block: 1024 * 1024, efficiency_score: 0.85,
1452 }
1453 }
1454
1455 fn estimate_type_parameter_size(
1457 &self,
1458 param_type: &str,
1459 total_size: usize,
1460 param_count: usize,
1461 ) -> usize {
1462 if param_type.starts_with('\'') {
1463 return 0; }
1465
1466 match param_type {
1467 "u8" | "i8" | "bool" => 1,
1468 "u16" | "i16" => 2,
1469 "u32" | "i32" | "f32" => 4,
1470 "u64" | "i64" | "f64" => 8,
1471 "usize" | "isize" => std::mem::size_of::<usize>(),
1472 _ => {
1473 if param_count > 0 {
1475 total_size / param_count
1476 } else {
1477 std::mem::size_of::<usize>()
1478 }
1479 }
1480 }
1481 }
1482}
1483
1484#[cfg(test)]
1485mod tests {
1486 use crate::core::tracker::memory_tracker::MemoryTracker;
1487 use crate::core::types::*;
1488
1489 fn create_test_tracker() -> MemoryTracker {
1490 MemoryTracker::new()
1491 }
1492
1493 #[test]
1494 fn test_estimate_alignment() {
1495 let tracker = create_test_tracker();
1496
1497 assert_eq!(tracker.estimate_alignment("u64", 8), 8);
1499 assert_eq!(tracker.estimate_alignment("i64", 8), 8);
1500 assert_eq!(tracker.estimate_alignment("f64", 8), 8);
1501 assert_eq!(tracker.estimate_alignment("u32", 4), 4);
1502 assert_eq!(tracker.estimate_alignment("i32", 4), 4);
1503 assert_eq!(tracker.estimate_alignment("f32", 4), 4);
1504 assert_eq!(tracker.estimate_alignment("u16", 2), 2);
1505 assert_eq!(tracker.estimate_alignment("i16", 2), 2);
1506 assert_eq!(tracker.estimate_alignment("u8", 1), 1);
1507 assert_eq!(tracker.estimate_alignment("i8", 1), 1);
1508 assert_eq!(tracker.estimate_alignment("bool", 1), 1);
1509
1510 assert_eq!(
1512 tracker.estimate_alignment("usize", 8),
1513 std::mem::size_of::<usize>()
1514 );
1515 assert_eq!(
1516 tracker.estimate_alignment("isize", 8),
1517 std::mem::size_of::<usize>()
1518 );
1519 assert_eq!(
1520 tracker.estimate_alignment("*const T", 8),
1521 std::mem::size_of::<usize>()
1522 );
1523
1524 assert_eq!(tracker.estimate_alignment("SomeStruct", 1), 1);
1526 assert_eq!(tracker.estimate_alignment("SomeStruct", 3), 2);
1527 assert_eq!(tracker.estimate_alignment("SomeStruct", 7), 4);
1528 assert_eq!(tracker.estimate_alignment("SomeStruct", 16), 8);
1529 }
1530
1531 #[test]
1532 fn test_estimate_type_size() {
1533 let tracker = create_test_tracker();
1534
1535 assert_eq!(tracker.estimate_type_size("u8"), 1);
1537 assert_eq!(tracker.estimate_type_size("i8"), 1);
1538 assert_eq!(tracker.estimate_type_size("bool"), 1);
1539 assert_eq!(tracker.estimate_type_size("u16"), 2);
1540 assert_eq!(tracker.estimate_type_size("i16"), 2);
1541 assert_eq!(tracker.estimate_type_size("u32"), 4);
1542 assert_eq!(tracker.estimate_type_size("i32"), 4);
1543 assert_eq!(tracker.estimate_type_size("f32"), 4);
1544 assert_eq!(tracker.estimate_type_size("u64"), 8);
1545 assert_eq!(tracker.estimate_type_size("i64"), 8);
1546 assert_eq!(tracker.estimate_type_size("f64"), 8);
1547 assert_eq!(
1548 tracker.estimate_type_size("usize"),
1549 std::mem::size_of::<usize>()
1550 );
1551 assert_eq!(
1552 tracker.estimate_type_size("isize"),
1553 std::mem::size_of::<usize>()
1554 );
1555
1556 assert_eq!(tracker.estimate_type_size("String"), 24);
1558 assert_eq!(tracker.estimate_type_size("Vec<i32>"), 24);
1559 assert_eq!(tracker.estimate_type_size("HashMap<String, i32>"), 48);
1560 assert_eq!(
1561 tracker.estimate_type_size("Box<i32>"),
1562 std::mem::size_of::<usize>()
1563 );
1564
1565 assert_eq!(tracker.estimate_type_size("UnknownType"), 8);
1567 }
1568
1569 #[test]
1570 fn test_analyze_memory_layout() {
1571 let tracker = create_test_tracker();
1572
1573 let vec_layout = tracker.analyze_memory_layout("Vec<i32>", 24);
1575 assert!(vec_layout.is_some());
1576 let layout = vec_layout.unwrap();
1577 assert_eq!(layout.total_size, 24);
1578 assert_eq!(layout.alignment, 4); assert_eq!(layout.field_layout.len(), 4); assert!(layout.container_analysis.is_some());
1581
1582 let string_layout = tracker.analyze_memory_layout("String", 24);
1584 assert!(string_layout.is_some());
1585 let layout = string_layout.unwrap();
1586 assert_eq!(layout.total_size, 24);
1587 assert_eq!(layout.field_layout.len(), 5); let unknown_layout = tracker.analyze_memory_layout("UnknownType", 16);
1591 assert!(unknown_layout.is_some());
1592 let layout = unknown_layout.unwrap();
1593 assert_eq!(layout.total_size, 16);
1594 assert!(!layout.field_layout.is_empty());
1595 }
1596
1597 #[test]
1598 fn test_analyze_memory_fragmentation() {
1599 let tracker = create_test_tracker();
1600
1601 let fragmentation = tracker.analyze_memory_fragmentation();
1602
1603 assert_eq!(fragmentation.free_block_count, 0); assert!(fragmentation.free_block_distribution.is_empty()); assert!(fragmentation.fragmentation_metrics.external_fragmentation >= 0.0);
1610 assert!(fragmentation.fragmentation_metrics.external_fragmentation <= 1.0);
1611 assert_eq!(
1612 fragmentation.fragmentation_metrics.internal_fragmentation,
1613 0.0
1614 ); match fragmentation.fragmentation_metrics.severity_level {
1618 FragmentationSeverity::Low
1619 | FragmentationSeverity::Moderate
1620 | FragmentationSeverity::High
1621 | FragmentationSeverity::Critical => {
1622 }
1624 }
1625 }
1626
1627 #[test]
1628 fn test_classify_container_type() {
1629 let tracker = create_test_tracker();
1630
1631 let vec_type = tracker.classify_container_type("Vec<i32>");
1633 match vec_type {
1634 ContainerType::Vec {
1635 element_type,
1636 element_size,
1637 } => {
1638 assert_eq!(element_type, "T");
1639 assert_eq!(element_size, 8);
1640 }
1641 _ => panic!("Expected Vec container type"),
1642 }
1643
1644 let hashmap_type = tracker.classify_container_type("HashMap<String, i32>");
1646 match hashmap_type {
1647 ContainerType::HashMap {
1648 key_type,
1649 value_type,
1650 key_size,
1651 value_size,
1652 } => {
1653 assert_eq!(key_type, "K");
1654 assert_eq!(value_type, "V");
1655 assert_eq!(key_size, 8);
1656 assert_eq!(value_size, 8);
1657 }
1658 _ => panic!("Expected HashMap container type"),
1659 }
1660
1661 let box_type = tracker.classify_container_type("Box<String>");
1663 match box_type {
1664 ContainerType::Box {
1665 boxed_type,
1666 boxed_size,
1667 } => {
1668 assert_eq!(boxed_type, "T");
1669 assert_eq!(boxed_size, 8);
1670 }
1671 _ => panic!("Expected Box container type"),
1672 }
1673
1674 let string_type = tracker.classify_container_type("String");
1676 match string_type {
1677 ContainerType::String => {
1678 }
1680 _ => panic!("Expected String container type"),
1681 }
1682
1683 let other_type = tracker.classify_container_type("CustomStruct");
1685 match other_type {
1686 ContainerType::Other { type_name } => {
1687 assert_eq!(type_name, "CustomStruct");
1688 }
1689 _ => panic!("Expected Other container type"),
1690 }
1691 }
1692
1693 #[test]
1694 fn test_analyze_capacity_utilization() {
1695 let tracker = create_test_tracker();
1696
1697 let vec_type = ContainerType::Vec {
1699 element_type: "i32".to_string(),
1700 element_size: 4,
1701 };
1702 let utilization = tracker.analyze_capacity_utilization(&vec_type, 100);
1703
1704 assert!(utilization.current_capacity > 0);
1705 assert_eq!(utilization.current_length, 100);
1706 assert!(utilization.utilization_ratio > 0.0);
1707 assert!(utilization.utilization_ratio <= 1.0);
1708 match utilization.efficiency_assessment {
1711 UtilizationEfficiency::Excellent
1712 | UtilizationEfficiency::Good
1713 | UtilizationEfficiency::Fair
1714 | UtilizationEfficiency::Poor { .. } => {
1715 }
1717 }
1718
1719 let box_type = ContainerType::Box {
1721 boxed_type: "i32".to_string(),
1722 boxed_size: 4,
1723 };
1724 let box_utilization = tracker.analyze_capacity_utilization(&box_type, 4);
1725 assert_eq!(box_utilization.utilization_ratio, 1.0);
1726 }
1727
1728 #[test]
1729 fn test_detect_reallocation_patterns() {
1730 let tracker = create_test_tracker();
1731
1732 let vec_type = ContainerType::Vec {
1734 element_type: "i32".to_string(),
1735 element_size: 4,
1736 };
1737 let patterns = tracker.detect_reallocation_patterns(&vec_type, 100);
1738
1739 match patterns.frequency_assessment {
1740 ReallocationFrequency::None
1741 | ReallocationFrequency::Low
1742 | ReallocationFrequency::Moderate
1743 | ReallocationFrequency::High { .. } => {
1744 }
1746 }
1747
1748 match patterns.growth_pattern {
1749 GrowthPattern::Exponential => {
1750 }
1752 _ => panic!("Expected exponential growth pattern for Vec"),
1753 }
1754
1755 assert!(!patterns.optimization_suggestions.is_empty());
1757
1758 let box_type = ContainerType::Box {
1760 boxed_type: "i32".to_string(),
1761 boxed_size: 4,
1762 };
1763 let box_patterns = tracker.detect_reallocation_patterns(&box_type, 4);
1764 match box_patterns.frequency_assessment {
1765 ReallocationFrequency::None => {
1766 }
1768 _ => panic!("Expected no reallocations for Box"),
1769 }
1770 }
1771
1772 #[test]
1773 fn test_calculate_container_efficiency_metrics() {
1774 let tracker = create_test_tracker();
1775
1776 let vec_type = ContainerType::Vec {
1777 element_type: "i32".to_string(),
1778 element_size: 4,
1779 };
1780 let capacity_util = CapacityUtilization {
1781 current_capacity: 100,
1782 current_length: 75,
1783 utilization_ratio: 0.75,
1784 wasted_space: 25,
1785 efficiency_assessment: UtilizationEfficiency::Good,
1786 };
1787 let realloc_patterns = ReallocationPatterns {
1788 frequency_assessment: ReallocationFrequency::Moderate,
1789 growth_pattern: GrowthPattern::Exponential,
1790 estimated_reallocations: 2,
1791 optimization_suggestions: vec!["test".to_string()],
1792 };
1793
1794 let metrics = tracker.calculate_container_efficiency_metrics(
1795 &vec_type,
1796 100,
1797 &capacity_util,
1798 &realloc_patterns,
1799 );
1800
1801 assert!(metrics.memory_overhead >= 0.0);
1802 assert!(metrics.memory_overhead <= 1.0);
1803 assert!(metrics.cache_efficiency >= 0.0);
1804 assert!(metrics.cache_efficiency <= 100.0);
1805 assert!(metrics.health_score >= 0.0);
1806 assert!(metrics.health_score <= 100.0);
1807
1808 match metrics.access_efficiency {
1809 AccessEfficiency::Sequential => {
1810 }
1812 _ => {
1813 }
1815 }
1816 }
1817
1818 #[test]
1819 fn test_analyze_generic_type() {
1820 let tracker = create_test_tracker();
1821
1822 let generic_info = tracker.analyze_generic_type("Vec<String>", 24);
1824 assert!(generic_info.is_some());
1825 let info = generic_info.unwrap();
1826 assert_eq!(info.base_type, "Vec");
1827 assert!(!info.type_parameters.is_empty());
1828 assert!(!info.constraints.is_empty());
1829
1830 let non_generic = tracker.analyze_generic_type("String", 24);
1832 assert!(non_generic.is_none());
1833
1834 let complex_generic = tracker.analyze_generic_type("HashMap<String, Vec<i32>>", 48);
1836 assert!(complex_generic.is_some());
1837 let complex_info = complex_generic.unwrap();
1838 assert_eq!(complex_info.base_type, "HashMap");
1839 assert_eq!(complex_info.type_parameters.len(), 2);
1840 }
1841
1842 #[test]
1843 fn test_analyze_dynamic_type() {
1844 let tracker = create_test_tracker();
1845
1846 let dyn_info = tracker.analyze_dynamic_type("Box<dyn Display>", 16);
1848 assert!(dyn_info.is_some());
1849 let info = dyn_info.unwrap();
1850 assert!(!info.trait_name.is_empty());
1851 assert!(info.vtable_info.method_count > 0);
1852 assert!(info.dispatch_overhead.indirect_call_overhead_ns > 0.0);
1853
1854 let non_dyn = tracker.analyze_dynamic_type("String", 24);
1856 assert!(non_dyn.is_none());
1857 }
1858
1859 #[test]
1860 fn test_collect_runtime_state() {
1861 let tracker = create_test_tracker();
1862
1863 let runtime_state = tracker.collect_runtime_state();
1864
1865 assert!(runtime_state.cpu_usage.current_usage_percent >= 0.0);
1867 assert!(runtime_state.cpu_usage.current_usage_percent <= 100.0);
1868 assert!(runtime_state.cpu_usage.average_usage_percent >= 0.0);
1869 assert!(runtime_state.cpu_usage.peak_usage_percent >= 0.0);
1870 match runtime_state.memory_pressure.pressure_level {
1874 MemoryPressureLevel::Low
1875 | MemoryPressureLevel::Moderate
1876 | MemoryPressureLevel::High
1877 | MemoryPressureLevel::Critical => {
1878 }
1880 }
1881 assert!(runtime_state.memory_pressure.available_memory_percent >= 0.0);
1882 assert!(runtime_state.memory_pressure.available_memory_percent <= 100.0);
1883 assert!(runtime_state.cache_performance.l1_hit_rate >= 0.0);
1887 assert!(runtime_state.cache_performance.l1_hit_rate <= 1.0);
1888 assert!(runtime_state.cache_performance.l2_hit_rate >= 0.0);
1889 assert!(runtime_state.cache_performance.l2_hit_rate <= 1.0);
1890 assert!(runtime_state.cache_performance.l3_hit_rate >= 0.0);
1891 assert!(runtime_state.cache_performance.l3_hit_rate <= 1.0);
1892 assert!(runtime_state.cache_performance.cache_miss_penalty_ns >= 0.0);
1893
1894 assert!(!runtime_state.allocator_state.allocator_type.is_empty());
1896 assert!(runtime_state.allocator_state.heap_size > 0);
1897 assert!(runtime_state.allocator_state.efficiency_score >= 0.0);
1899 assert!(runtime_state.allocator_state.efficiency_score <= 1.0);
1900
1901 assert!(runtime_state.gc_info.is_none());
1903 }
1904
1905 #[test]
1906 fn test_analyze_type_relationships() {
1907 let tracker = create_test_tracker();
1908
1909 let relationships = tracker.analyze_type_relationships("Vec<String>");
1910 assert!(relationships.is_some());
1911 let rel = relationships.unwrap();
1912 assert_eq!(rel.type_name, "Vec<String>");
1913 assert!(rel.complexity_score > 0);
1914 assert_eq!(rel.inheritance_depth, 0); assert_eq!(rel.composition_breadth, 0);
1916 }
1917
1918 #[test]
1919 fn test_calculate_type_complexity() {
1920 let tracker = create_test_tracker();
1921
1922 let simple_complexity = tracker.calculate_type_complexity("String");
1924 assert_eq!(simple_complexity, 1);
1925
1926 let generic_complexity = tracker.calculate_type_complexity("Vec<String>");
1928 assert!(generic_complexity > 1);
1929
1930 let trait_complexity = tracker.calculate_type_complexity("Box<dyn Display>");
1932 assert!(trait_complexity > 2);
1933
1934 let impl_complexity = tracker.calculate_type_complexity("impl Iterator<Item = String>");
1936 assert!(impl_complexity > 2);
1937
1938 let complex_complexity =
1940 tracker.calculate_type_complexity("HashMap<String, Vec<i32>, RandomState>");
1941 assert!(complex_complexity > 3);
1942 }
1943
1944 #[test]
1945 fn test_track_type_usage() {
1946 let tracker = create_test_tracker();
1947
1948 let usage_info = tracker.track_type_usage("String");
1950 assert!(usage_info.is_some());
1951 let info = usage_info.unwrap();
1952 assert_eq!(info.type_name, "String");
1953 assert!(info.total_usage_count >= 1);
1954
1955 assert!(info.performance_impact.performance_score >= 0.0);
1957 assert!(info.performance_impact.performance_score <= 100.0);
1958 assert!(info.performance_impact.memory_efficiency_score >= 0.0);
1959 assert!(info.performance_impact.memory_efficiency_score <= 100.0);
1960 assert!(info.performance_impact.cpu_efficiency_score >= 0.0);
1961 assert!(info.performance_impact.cpu_efficiency_score <= 100.0);
1962 assert!(info.performance_impact.cache_efficiency_score >= 0.0);
1963 assert!(info.performance_impact.cache_efficiency_score <= 100.0);
1964 assert!(!info
1965 .performance_impact
1966 .optimization_recommendations
1967 .is_empty());
1968 }
1969
1970 #[test]
1971 fn test_analyze_stack_allocation() {
1972 let tracker = create_test_tracker();
1973
1974 let stack_ptr = 0x7fff_8000_0000;
1976 let stack_info = tracker.analyze_stack_allocation("i32", stack_ptr);
1977 assert!(stack_info.is_some());
1978 let info = stack_info.unwrap();
1979 assert_eq!(info.var_name, "stack_var");
1981 assert!(info.stack_offset >= 0);
1982 assert_eq!(info.size, 4); assert_eq!(info.function_name, "unknown_function");
1984 match info.scope_info.scope_type {
1987 ScopeType::Function => {
1988 }
1990 _ => panic!("Expected function scope type"),
1991 }
1992
1993 let heap_ptr = 0x1000_0000;
1995 let non_stack_info = tracker.analyze_stack_allocation("i32", heap_ptr);
1996 assert!(non_stack_info.is_none());
1997 }
1998
1999 #[test]
2000 fn test_estimate_stack_depth() {
2001 let tracker = create_test_tracker();
2002
2003 let stack_start = 0x7fff_0000_0000;
2004
2005 let depth1 = tracker.estimate_stack_depth(stack_start);
2007 assert_eq!(depth1, 0);
2008
2009 let depth2 = tracker.estimate_stack_depth(stack_start + 4096);
2010 assert_eq!(depth2, 1);
2011
2012 let depth3 = tracker.estimate_stack_depth(stack_start + 8192);
2013 assert_eq!(depth3, 2);
2014
2015 let non_stack_depth = tracker.estimate_stack_depth(0x1000_0000);
2017 assert_eq!(non_stack_depth, 0);
2018 }
2019
2020 #[test]
2021 fn test_extract_base_type() {
2022 let tracker = create_test_tracker();
2023
2024 assert_eq!(tracker.extract_base_type("Vec<String>"), "Vec");
2025 assert_eq!(tracker.extract_base_type("HashMap<K, V>"), "HashMap");
2026 assert_eq!(tracker.extract_base_type("String"), "String");
2027 assert_eq!(tracker.extract_base_type("Box<dyn Display>"), "Box");
2028 }
2029
2030 #[test]
2031 fn test_extract_trait_name() {
2032 let tracker = create_test_tracker();
2033
2034 assert_eq!(tracker.extract_trait_name("Box<dyn Display>"), "Display");
2035 assert_eq!(tracker.extract_trait_name("dyn Iterator"), "Iterator");
2036 assert_eq!(tracker.extract_trait_name("String"), "Unknown");
2037 }
2038
2039 #[test]
2040 fn test_estimate_cache_miss_rate() {
2041 let tracker = create_test_tracker();
2042
2043 let small_miss_rate = tracker.estimate_cache_miss_rate("i32", 32.0);
2045 assert!(small_miss_rate <= 0.1);
2046
2047 let medium_miss_rate = tracker.estimate_cache_miss_rate("SomeStruct", 128.0);
2049 assert!(medium_miss_rate > 0.1);
2050 assert!(medium_miss_rate <= 0.2);
2051
2052 let large_container_miss_rate = tracker.estimate_cache_miss_rate("Vec<i32>", 1024.0);
2054 assert!(large_container_miss_rate > 0.2);
2055 assert!(large_container_miss_rate <= 0.3);
2056
2057 let very_large_miss_rate = tracker.estimate_cache_miss_rate("LargeStruct", 4096.0);
2059 assert!(very_large_miss_rate > 0.3);
2060 }
2061}