1use serde::{Deserialize, Serialize};
7use std::thread;
8
9use super::access_tracking::MemoryAccessTrackingInfo;
11use super::drop_chain::DropChainAnalysis;
12use super::dynamic_type::DynamicTypeInfo;
13use super::fragmentation::EnhancedFragmentationAnalysis;
14use super::generic::{GenericInstantiationInfo, GenericTypeInfo};
15use super::lifecycle::ObjectLifecycleInfo;
16use super::memory_layout::MemoryLayoutInfo;
17use super::ownership::TypeRelationshipInfo;
18use super::runtime_state::RuntimeStateInfo;
19use super::smart_pointer::SmartPointerInfo;
20use super::stack::StackAllocationInfo;
21use super::temporary::TemporaryObjectInfo;
22use super::tracking::FunctionCallTrackingInfo;
23
24#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
29pub struct BorrowInfo {
30 pub immutable_borrows: usize,
32 pub mutable_borrows: usize,
34 pub max_concurrent_borrows: usize,
36 pub last_borrow_timestamp: Option<u64>,
38
39 #[serde(default)]
41 pub _source: Option<String>,
42 #[serde(default)]
44 pub _confidence: Option<String>,
45}
46
47#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
52pub struct CloneInfo {
53 pub clone_count: usize,
55 pub is_clone: bool,
57 pub original_ptr: Option<usize>,
59
60 #[serde(default)]
62 pub _source: Option<String>,
63 #[serde(default)]
65 pub _confidence: Option<String>,
66}
67
68#[derive(Debug, Clone, PartialEq)]
73pub struct AllocationInfo {
74 pub ptr: usize,
76 pub size: usize,
78 pub var_name: Option<String>,
80 pub type_name: Option<String>,
82 pub scope_name: Option<String>,
84 pub timestamp_alloc: u64,
86 pub timestamp_dealloc: Option<u64>,
88 pub thread_id: thread::ThreadId,
90 pub thread_id_u64: u64,
92 pub borrow_count: usize,
94 pub stack_trace: Option<Vec<String>>,
96 pub is_leaked: bool,
98 pub lifetime_ms: Option<u64>,
100 pub borrow_info: Option<BorrowInfo>,
102 pub clone_info: Option<CloneInfo>,
104 pub ownership_history_available: bool,
106 pub smart_pointer_info: Option<SmartPointerInfo>,
108 pub memory_layout: Option<MemoryLayoutInfo>,
110 pub module_path: Option<String>,
112 pub stack_ptr: Option<usize>,
114 pub generation_id: usize,
116 pub task_id: Option<u64>,
118 pub generic_info: Option<GenericTypeInfo>,
120 pub dynamic_type_info: Option<DynamicTypeInfo>,
122 pub runtime_state: Option<RuntimeStateInfo>,
124 pub stack_allocation: Option<StackAllocationInfo>,
126 pub temporary_object: Option<TemporaryObjectInfo>,
128 pub fragmentation_analysis: Option<EnhancedFragmentationAnalysis>,
130 pub generic_instantiation: Option<GenericInstantiationInfo>,
132 pub type_relationships: Option<TypeRelationshipInfo>,
134 pub type_usage: Option<TypeUsageInfo>,
136 pub function_call_tracking: Option<FunctionCallTrackingInfo>,
138 pub lifecycle_tracking: Option<ObjectLifecycleInfo>,
140 pub access_tracking: Option<MemoryAccessTrackingInfo>,
142 pub drop_chain_analysis: Option<DropChainAnalysis>,
144}
145
146impl From<crate::core::types::AllocationInfo> for AllocationInfo {
147 fn from(old: crate::core::types::AllocationInfo) -> Self {
148 let thread_id = thread::current().id();
151
152 let borrow_info = old.borrow_info.map(|b| BorrowInfo {
154 immutable_borrows: b.immutable_borrows,
155 mutable_borrows: b.mutable_borrows,
156 max_concurrent_borrows: b.max_concurrent_borrows,
157 last_borrow_timestamp: b.last_borrow_timestamp,
158 _source: None,
159 _confidence: None,
160 });
161
162 let clone_info = old.clone_info.map(|c| CloneInfo {
164 clone_count: c.clone_count,
165 is_clone: c.is_clone,
166 original_ptr: c.original_ptr,
167 _source: None,
168 _confidence: None,
169 });
170
171 let smart_pointer_info =
174 old.smart_pointer_info
175 .map(|s| super::smart_pointer::SmartPointerInfo {
176 data_ptr: s.data_ptr,
177 cloned_from: s.cloned_from,
178 clones: s.clones,
179 ref_count_history: s
180 .ref_count_history
181 .iter()
182 .map(|r| super::smart_pointer::RefCountSnapshot {
183 timestamp: r.timestamp,
184 strong_count: r.strong_count,
185 weak_count: r.weak_count,
186 })
187 .collect(),
188 weak_count: s.weak_count,
189 is_weak_reference: s.is_weak_reference,
190 is_data_owner: s.is_data_owner,
191 is_implicitly_deallocated: s.is_implicitly_deallocated,
192 pointer_type: match s.pointer_type {
193 crate::core::types::SmartPointerType::Rc => {
194 super::smart_pointer::SmartPointerType::Rc
195 }
196 crate::core::types::SmartPointerType::Arc => {
197 super::smart_pointer::SmartPointerType::Arc
198 }
199 crate::core::types::SmartPointerType::RcWeak => {
200 super::smart_pointer::SmartPointerType::RcWeak
201 }
202 crate::core::types::SmartPointerType::ArcWeak => {
203 super::smart_pointer::SmartPointerType::ArcWeak
204 }
205 crate::core::types::SmartPointerType::Box => {
206 super::smart_pointer::SmartPointerType::Box
207 }
208 },
209 });
210
211 Self {
212 ptr: old.ptr,
213 size: old.size,
214 var_name: old.var_name,
215 type_name: old.type_name,
216 scope_name: old.scope_name,
217 timestamp_alloc: old.timestamp_alloc,
218 timestamp_dealloc: old.timestamp_dealloc,
219 thread_id,
220 thread_id_u64: old.thread_id.parse().unwrap_or_else(|_| {
221 tracing::warn!(
222 "Failed to parse thread_id: '{}', defaulting to 0",
223 old.thread_id
224 );
225 0
226 }),
227 borrow_count: old.borrow_count,
228 stack_trace: old.stack_trace,
229 is_leaked: old.is_leaked,
230 lifetime_ms: old.lifetime_ms,
231 borrow_info,
232 clone_info,
233 ownership_history_available: old.ownership_history_available,
234 smart_pointer_info,
235 memory_layout: old.memory_layout.map(Into::into),
237 generic_info: old.generic_info.map(Into::into),
238 dynamic_type_info: old.dynamic_type_info.map(Into::into),
239 runtime_state: old.runtime_state.map(Into::into),
240 stack_allocation: old.stack_allocation.map(Into::into),
241 temporary_object: old.temporary_object.map(Into::into),
242 fragmentation_analysis: old.fragmentation_analysis.map(Into::into),
243 generic_instantiation: old.generic_instantiation.map(Into::into),
244 type_relationships: old.type_relationships.map(Into::into),
245 type_usage: old.type_usage.map(Into::into),
246 function_call_tracking: old.function_call_tracking.map(Into::into),
247 lifecycle_tracking: old.lifecycle_tracking.map(Into::into),
248 access_tracking: old.access_tracking.map(Into::into),
249 drop_chain_analysis: old.drop_chain_analysis.map(Into::into),
250 module_path: None, stack_ptr: None,
252 task_id: None,
253 generation_id: 0, }
255 }
256}
257
258impl From<crate::capture::backends::core_types::AllocationInfo> for AllocationInfo {
259 fn from(info: crate::capture::backends::core_types::AllocationInfo) -> Self {
260 Self {
261 ptr: info.ptr,
262 size: info.size,
263 var_name: info.var_name,
264 type_name: info.type_name,
265 scope_name: None,
266 timestamp_alloc: info.allocated_at_ns,
267 timestamp_dealloc: None,
268 thread_id: std::thread::current().id(),
269 thread_id_u64: info.thread_id,
270 borrow_count: 0,
271 stack_trace: info.stack_trace,
272 is_leaked: false,
273 lifetime_ms: None,
274 module_path: None,
275 borrow_info: None,
276 clone_info: None,
277 ownership_history_available: false,
278 smart_pointer_info: None,
279 memory_layout: None,
280 generic_info: None,
281 dynamic_type_info: None,
282 runtime_state: None,
283 stack_allocation: None,
284 temporary_object: None,
285 fragmentation_analysis: None,
286 generic_instantiation: None,
287 type_relationships: None,
288 type_usage: None,
289 function_call_tracking: None,
290 lifecycle_tracking: None,
291 access_tracking: None,
292 drop_chain_analysis: None,
293 stack_ptr: None,
294 task_id: None,
295 generation_id: 0,
296 }
297 }
298}
299
300#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
302pub struct TypeUsageInfo {
303 pub type_name: String,
305 pub total_usage_count: u64,
307 pub usage_contexts: Vec<UsageContext>,
309 pub usage_timeline: Vec<UsageTimePoint>,
311 pub hot_paths: Vec<HotPath>,
313 pub performance_impact: TypePerformanceImpact,
315}
316
317#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
319pub struct UsageContext {
320 pub context_type: ContextType,
322 pub location: String,
324 pub frequency: u32,
326 pub performance_metrics: ContextPerformanceMetrics,
328}
329
330#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
332pub enum ContextType {
333 FunctionParameter,
335 FunctionReturn,
337 LocalVariable,
339 StructField,
341 EnumVariant,
343 TraitMethod,
345 GenericConstraint,
347 ClosureCapture,
349 AsyncContext,
351 UnsafeContext,
353}
354
355#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
357pub struct ContextPerformanceMetrics {
358 pub avg_execution_time_ns: f64,
360 pub allocation_frequency: f64,
362 pub cache_miss_rate: f64,
364 pub branch_misprediction_rate: f64,
366}
367
368#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
370pub struct UsageTimePoint {
371 pub timestamp: u64,
373 pub usage_count: u32,
375 pub memory_usage: usize,
377 pub performance_snapshot: PerformanceSnapshot,
379}
380
381#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
383pub struct PerformanceSnapshot {
384 pub cpu_usage: f64,
386 pub memory_usage: f64,
388 pub cache_hit_rate: f64,
390 pub throughput: f64,
392}
393
394#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
396pub struct HotPath {
397 pub path_id: String,
399 pub call_sequence: Vec<String>,
401 pub execution_frequency: u64,
403 pub total_execution_time_ns: u64,
405 pub avg_execution_time_ns: f64,
407 pub memory_allocations: u32,
409 pub bottlenecks: Vec<PerformanceBottleneck>,
411}
412
413#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
415pub struct PerformanceBottleneck {
416 pub bottleneck_type: BottleneckType,
418 pub location: String,
420 pub severity: ImpactLevel,
422 pub description: String,
424 pub optimization_suggestion: String,
426}
427
428#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
430pub enum BottleneckType {
431 MemoryAllocation,
433 MemoryDeallocation,
435 CacheMiss,
437 BranchMisprediction,
439 FunctionCall,
441 DataMovement,
443 Synchronization,
445 IO,
447}
448
449#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
451pub enum ImpactLevel {
452 Low,
454 Medium,
456 High,
458 Critical,
460}
461
462#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
464pub struct TypePerformanceImpact {
465 pub performance_score: f64,
467 pub memory_efficiency_score: f64,
469 pub cpu_efficiency_score: f64,
471 pub cache_efficiency_score: f64,
473 pub optimization_recommendations: Vec<OptimizationRecommendation>,
475}
476
477#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
479pub struct OptimizationRecommendation {
480 pub recommendation_type: RecommendationType,
482 pub priority: Priority,
484 pub description: String,
486 pub expected_improvement: f64,
488 pub implementation_difficulty: ImplementationDifficulty,
490}
491
492#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
494pub enum RecommendationType {
495 MemoryLayout,
497 AlgorithmChange,
499 DataStructureChange,
501 CachingStrategy,
503 MemoryPooling,
505 LazyInitialization,
507 Inlining,
509 Vectorization,
511 Parallelization,
513}
514
515#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
517pub enum Priority {
518 Low,
520 Medium,
522 High,
524 Critical,
526}
527
528#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
530pub enum ImplementationDifficulty {
531 Easy,
533 Medium,
535 Hard,
537 VeryHard,
539}
540
541impl Serialize for AllocationInfo {
543 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
544 where
545 S: serde::Serializer,
546 {
547 use serde::ser::SerializeStruct;
548 let mut state = serializer.serialize_struct("AllocationInfo", 25)?;
549 state.serialize_field("ptr", &self.ptr)?;
550 state.serialize_field("size", &self.size)?;
551 state.serialize_field("var_name", &self.var_name)?;
552 state.serialize_field("type_name", &self.type_name)?;
553 state.serialize_field("scope_name", &self.scope_name)?;
554 state.serialize_field("timestamp_alloc", &self.timestamp_alloc)?;
555 state.serialize_field("timestamp_dealloc", &self.timestamp_dealloc)?;
556 state.serialize_field("thread_id", &format!("{:?}", self.thread_id))?;
557 state.serialize_field("borrow_count", &self.borrow_count)?;
558 state.serialize_field("stack_trace", &self.stack_trace)?;
559 state.serialize_field("is_leaked", &self.is_leaked)?;
560 state.serialize_field("lifetime_ms", &self.lifetime_ms)?;
561 state.serialize_field("borrow_info", &self.borrow_info)?;
562 state.serialize_field("clone_info", &self.clone_info)?;
563 state.serialize_field(
564 "ownership_history_available",
565 &self.ownership_history_available,
566 )?;
567 state.serialize_field("smart_pointer_info", &self.smart_pointer_info)?;
568 state.serialize_field("memory_layout", &self.memory_layout)?;
569 state.serialize_field("generic_info", &self.generic_info)?;
570 state.serialize_field("dynamic_type_info", &self.dynamic_type_info)?;
571 state.serialize_field("runtime_state", &self.runtime_state)?;
572 state.serialize_field("stack_allocation", &self.stack_allocation)?;
573 state.serialize_field("temporary_object", &self.temporary_object)?;
574 state.serialize_field("fragmentation_analysis", &self.fragmentation_analysis)?;
575 state.serialize_field("generic_instantiation", &self.generic_instantiation)?;
576 state.serialize_field("type_relationships", &self.type_relationships)?;
577 state.serialize_field("type_usage", &self.type_usage)?;
578 state.serialize_field("function_call_tracking", &self.function_call_tracking)?;
579 state.serialize_field("lifecycle_tracking", &self.lifecycle_tracking)?;
580 state.serialize_field("access_tracking", &self.access_tracking)?;
581 state.serialize_field("drop_chain_analysis", &self.drop_chain_analysis)?;
582 state.serialize_field("module_path", &self.module_path)?;
583 state.end()
584 }
585}
586
587impl<'de> Deserialize<'de> for AllocationInfo {
589 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
590 where
591 D: serde::Deserializer<'de>,
592 {
593 #[derive(Deserialize)]
594 struct AllocationInfoHelper {
595 ptr: usize,
596 size: usize,
597 var_name: Option<String>,
598 type_name: Option<String>,
599 scope_name: Option<String>,
600 timestamp_alloc: u64,
601 timestamp_dealloc: Option<u64>,
602 #[serde(default)]
603 thread_id: String,
604 #[serde(default)]
605 thread_id_u64: u64,
606 borrow_count: usize,
607 stack_trace: Option<Vec<String>>,
608 is_leaked: bool,
609 lifetime_ms: Option<u64>,
610 borrow_info: Option<BorrowInfo>,
611 clone_info: Option<CloneInfo>,
612 ownership_history_available: Option<bool>,
613 smart_pointer_info: Option<SmartPointerInfo>,
614 memory_layout: Option<MemoryLayoutInfo>,
615 generic_info: Option<GenericTypeInfo>,
616 dynamic_type_info: Option<DynamicTypeInfo>,
617 runtime_state: Option<RuntimeStateInfo>,
618 stack_allocation: Option<StackAllocationInfo>,
619 temporary_object: Option<TemporaryObjectInfo>,
620 fragmentation_analysis: Option<EnhancedFragmentationAnalysis>,
621 generic_instantiation: Option<GenericInstantiationInfo>,
622 type_relationships: Option<TypeRelationshipInfo>,
623 type_usage: Option<TypeUsageInfo>,
624 function_call_tracking: Option<FunctionCallTrackingInfo>,
625 lifecycle_tracking: Option<ObjectLifecycleInfo>,
626 access_tracking: Option<MemoryAccessTrackingInfo>,
627 drop_chain_analysis: Option<DropChainAnalysis>,
628 module_path: Option<String>,
629 #[serde(default)]
630 generation_id: usize,
631 }
632
633 let helper = AllocationInfoHelper::deserialize(deserializer)?;
634 let thread_id = if !helper.thread_id.is_empty() {
636 thread::current().id()
639 } else {
640 thread::current().id()
641 };
642
643 Ok(AllocationInfo {
644 ptr: helper.ptr,
645 size: helper.size,
646 var_name: helper.var_name,
647 type_name: helper.type_name,
648 scope_name: helper.scope_name,
649 timestamp_alloc: helper.timestamp_alloc,
650 timestamp_dealloc: helper.timestamp_dealloc,
651 thread_id,
652 thread_id_u64: helper.thread_id_u64,
653 borrow_count: helper.borrow_count,
654 stack_trace: helper.stack_trace,
655 is_leaked: helper.is_leaked,
656 lifetime_ms: helper.lifetime_ms,
657 borrow_info: helper.borrow_info,
658 clone_info: helper.clone_info,
659 ownership_history_available: helper.ownership_history_available.unwrap_or(false),
660 smart_pointer_info: helper.smart_pointer_info,
661 memory_layout: helper.memory_layout,
662 generic_info: helper.generic_info,
663 dynamic_type_info: helper.dynamic_type_info,
664 runtime_state: helper.runtime_state,
665 stack_allocation: helper.stack_allocation,
666 temporary_object: helper.temporary_object,
667 fragmentation_analysis: helper.fragmentation_analysis,
668 generic_instantiation: helper.generic_instantiation,
669 type_relationships: helper.type_relationships,
670 type_usage: helper.type_usage,
671 function_call_tracking: helper.function_call_tracking,
672 lifecycle_tracking: helper.lifecycle_tracking,
673 access_tracking: helper.access_tracking,
674 drop_chain_analysis: helper.drop_chain_analysis,
675 module_path: helper.module_path,
676 stack_ptr: None,
677 task_id: None,
678 generation_id: helper.generation_id,
679 })
680 }
681}
682
683impl AllocationInfo {
684 pub fn new(ptr: usize, size: usize) -> Self {
702 crate::task_registry::global_registry().record_allocation(size);
704
705 let timestamp = std::time::SystemTime::now()
706 .duration_since(std::time::UNIX_EPOCH)
707 .unwrap_or_default()
708 .as_nanos() as u64;
709
710 Self {
711 ptr,
712 size,
713 var_name: None,
714 type_name: None,
715 scope_name: None,
716 timestamp_alloc: timestamp,
717 timestamp_dealloc: None,
718 thread_id: thread::current().id(),
719 thread_id_u64: {
720 use std::hash::{Hash, Hasher};
721 let mut hasher = std::collections::hash_map::DefaultHasher::new();
722 thread::current().id().hash(&mut hasher);
723 hasher.finish()
724 },
725 borrow_count: 0,
726 stack_trace: None,
727 is_leaked: false,
728 lifetime_ms: Some(1), borrow_info: None, clone_info: Some(CloneInfo {
731 clone_count: 0,
732 is_clone: false,
733 original_ptr: None,
734 _source: None,
735 _confidence: None,
736 }),
737 ownership_history_available: false, smart_pointer_info: None,
739 memory_layout: None,
740 generic_info: None,
741 dynamic_type_info: None,
742 runtime_state: None,
743 stack_allocation: None,
744 temporary_object: None,
745 fragmentation_analysis: None,
746 generic_instantiation: None,
747 type_relationships: None,
748 type_usage: None,
749 function_call_tracking: None,
750 lifecycle_tracking: None,
751 access_tracking: None,
752 drop_chain_analysis: None,
753 module_path: None,
754 stack_ptr: None,
755 task_id: crate::task_registry::TaskIdRegistry::current_task_id(),
756 generation_id: 0,
757 }
758 }
759
760 pub fn set_source_location(&mut self, file: &str, line: u32) {
762 let frame = format!("{}:{}", file, line);
763 self.stack_trace.get_or_insert_with(Vec::new).push(frame);
764 }
765
766 pub fn set_smart_pointer_info(&mut self, info: SmartPointerInfo) {
768 self.smart_pointer_info = Some(info);
769 }
770
771 pub fn mark_deallocated(&mut self) {
773 self.timestamp_dealloc = Some(
774 std::time::SystemTime::now()
775 .duration_since(std::time::UNIX_EPOCH)
776 .unwrap_or_default()
777 .as_nanos() as u64,
778 );
779 }
780
781 pub fn is_active(&self) -> bool {
783 self.timestamp_dealloc.is_none()
784 }
785
786 pub fn enhance_with_type_info(&mut self, type_name: &str) {
793 if self.timestamp_dealloc.is_none() {
794 let current_time = std::time::SystemTime::now()
795 .duration_since(std::time::UNIX_EPOCH)
796 .unwrap_or_default()
797 .as_nanos() as u64;
798 let elapsed_ns = current_time.saturating_sub(self.timestamp_alloc);
799 let elapsed_ms = elapsed_ns / 1_000_000;
800 self.lifetime_ms = Some(if elapsed_ms == 0 { 1 } else { elapsed_ms });
801 }
802
803 if type_name.contains("Rc<") || type_name.contains("Arc<") {
806 self.clone_info = Some(CloneInfo {
807 clone_count: 2,
808 is_clone: false,
809 original_ptr: None,
810 _source: Some("inferred".to_string()),
811 _confidence: Some("low".to_string()),
812 });
813
814 self.borrow_info = Some(BorrowInfo {
815 immutable_borrows: 5,
816 mutable_borrows: 0,
817 max_concurrent_borrows: 5,
818 last_borrow_timestamp: Some(self.timestamp_alloc + 1000000),
819 _source: Some("inferred".to_string()),
820 _confidence: Some("low".to_string()),
821 });
822 } else if type_name.contains("Vec<")
823 || type_name.contains("String")
824 || type_name.contains("HashMap")
825 {
826 self.borrow_info = Some(BorrowInfo {
827 immutable_borrows: 4,
828 mutable_borrows: 2,
829 max_concurrent_borrows: 3,
830 last_borrow_timestamp: Some(self.timestamp_alloc + 800000),
831 _source: Some("inferred".to_string()),
832 _confidence: Some("low".to_string()),
833 });
834 } else if type_name.contains("Box<") {
835 self.clone_info = Some(CloneInfo {
836 clone_count: 0,
837 is_clone: false,
838 original_ptr: None,
839 _source: Some("inferred".to_string()),
840 _confidence: Some("low".to_string()),
841 });
842
843 self.borrow_info = Some(BorrowInfo {
844 immutable_borrows: 2,
845 mutable_borrows: 1,
846 max_concurrent_borrows: 1,
847 last_borrow_timestamp: Some(self.timestamp_alloc + 300000),
848 _source: Some("inferred".to_string()),
849 _confidence: Some("low".to_string()),
850 });
851 }
852 }
853
854 pub fn enhance_with_inference(&mut self, engine: &crate::capture::inference::InferenceEngine) {
858 let type_name = self.type_name.as_deref();
859
860 let inferred_borrow = engine.infer_borrow_info(type_name);
861 self.borrow_info = Some(BorrowInfo {
862 immutable_borrows: inferred_borrow.immutable_borrows,
863 mutable_borrows: inferred_borrow.mutable_borrows,
864 max_concurrent_borrows: inferred_borrow.max_concurrent_borrows,
865 last_borrow_timestamp: None,
866 _source: Some("inferred".to_string()),
867 _confidence: Some(format!("{:?}", inferred_borrow._confidence).to_lowercase()),
868 });
869
870 let inferred_sp = engine.infer_smart_pointer(type_name);
871 if inferred_sp.pointer_type != crate::capture::inference::SmartPointerType::Unknown {
872 self.clone_info = Some(CloneInfo {
873 clone_count: inferred_sp.ref_count.unwrap_or(0),
874 is_clone: false,
875 original_ptr: None,
876 _source: Some("inferred".to_string()),
877 _confidence: Some(format!("{:?}", inferred_sp._confidence).to_lowercase()),
878 });
879 }
880 }
881}
882
883#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
885pub struct RiskDistribution {
886 pub low_risk: usize,
888 pub medium_risk: usize,
890 pub high_risk: usize,
892 pub critical_risk: usize,
894}
895
896impl From<crate::core::types::TypeUsageInfo> for TypeUsageInfo {
898 fn from(old: crate::core::types::TypeUsageInfo) -> Self {
899 Self {
900 type_name: old.type_name,
901 total_usage_count: old.total_usage_count,
902 usage_contexts: old
903 .usage_contexts
904 .into_iter()
905 .map(|c| UsageContext {
906 context_type: match c.context_type {
907 crate::core::types::ContextType::FunctionParameter => {
908 ContextType::FunctionParameter
909 }
910 crate::core::types::ContextType::FunctionReturn => {
911 ContextType::FunctionReturn
912 }
913 crate::core::types::ContextType::LocalVariable => {
914 ContextType::LocalVariable
915 }
916 crate::core::types::ContextType::StructField => ContextType::StructField,
917 crate::core::types::ContextType::EnumVariant => ContextType::EnumVariant,
918 crate::core::types::ContextType::TraitMethod => ContextType::TraitMethod,
919 crate::core::types::ContextType::GenericConstraint => {
920 ContextType::GenericConstraint
921 }
922 crate::core::types::ContextType::ClosureCapture => {
923 ContextType::ClosureCapture
924 }
925 crate::core::types::ContextType::AsyncContext => ContextType::AsyncContext,
926 crate::core::types::ContextType::UnsafeContext => {
927 ContextType::UnsafeContext
928 }
929 },
930 location: c.location,
931 frequency: c.frequency,
932 performance_metrics: ContextPerformanceMetrics {
933 avg_execution_time_ns: c.performance_metrics.avg_execution_time_ns,
934 allocation_frequency: c.performance_metrics.allocation_frequency,
935 cache_miss_rate: c.performance_metrics.cache_miss_rate,
936 branch_misprediction_rate: c.performance_metrics.branch_misprediction_rate,
937 },
938 })
939 .collect(),
940 usage_timeline: old
941 .usage_timeline
942 .into_iter()
943 .map(|t| UsageTimePoint {
944 timestamp: t.timestamp,
945 usage_count: t.usage_count,
946 memory_usage: t.memory_usage,
947 performance_snapshot: PerformanceSnapshot {
948 cpu_usage: t.performance_snapshot.cpu_usage,
949 memory_usage: t.performance_snapshot.memory_usage,
950 cache_hit_rate: t.performance_snapshot.cache_hit_rate,
951 throughput: t.performance_snapshot.throughput,
952 },
953 })
954 .collect(),
955 hot_paths: old
956 .hot_paths
957 .into_iter()
958 .map(|h| HotPath {
959 path_id: h.path_id,
960 call_sequence: h.call_sequence,
961 execution_frequency: h.execution_frequency,
962 total_execution_time_ns: h.total_execution_time_ns,
963 avg_execution_time_ns: h.avg_execution_time_ns,
964 memory_allocations: h.memory_allocations,
965 bottlenecks: h
966 .bottlenecks
967 .into_iter()
968 .map(|b| PerformanceBottleneck {
969 bottleneck_type: match b.bottleneck_type {
970 crate::core::types::BottleneckType::MemoryAllocation => {
971 BottleneckType::MemoryAllocation
972 }
973 crate::core::types::BottleneckType::MemoryDeallocation => {
974 BottleneckType::MemoryDeallocation
975 }
976 crate::core::types::BottleneckType::CacheMiss => {
977 BottleneckType::CacheMiss
978 }
979 crate::core::types::BottleneckType::BranchMisprediction => {
980 BottleneckType::BranchMisprediction
981 }
982 crate::core::types::BottleneckType::FunctionCall => {
983 BottleneckType::FunctionCall
984 }
985 crate::core::types::BottleneckType::DataMovement => {
986 BottleneckType::DataMovement
987 }
988 crate::core::types::BottleneckType::Synchronization => {
989 BottleneckType::Synchronization
990 }
991 crate::core::types::BottleneckType::IO => BottleneckType::IO,
992 },
993 location: b.location,
994 severity: match b.severity {
995 crate::core::types::ImpactLevel::Low => ImpactLevel::Low,
996 crate::core::types::ImpactLevel::Medium => ImpactLevel::Medium,
997 crate::core::types::ImpactLevel::High => ImpactLevel::High,
998 crate::core::types::ImpactLevel::Critical => ImpactLevel::Critical,
999 },
1000 description: b.description,
1001 optimization_suggestion: b.optimization_suggestion,
1002 })
1003 .collect(),
1004 })
1005 .collect(),
1006 performance_impact: TypePerformanceImpact {
1007 performance_score: old.performance_impact.performance_score,
1008 memory_efficiency_score: old.performance_impact.memory_efficiency_score,
1009 cpu_efficiency_score: old.performance_impact.cpu_efficiency_score,
1010 cache_efficiency_score: old.performance_impact.cache_efficiency_score,
1011 optimization_recommendations: old
1012 .performance_impact
1013 .optimization_recommendations
1014 .into_iter()
1015 .map(|r| OptimizationRecommendation {
1016 recommendation_type: match r.recommendation_type {
1017 crate::core::types::RecommendationType::MemoryLayout => {
1018 RecommendationType::MemoryLayout
1019 }
1020 crate::core::types::RecommendationType::AlgorithmChange => {
1021 RecommendationType::AlgorithmChange
1022 }
1023 crate::core::types::RecommendationType::DataStructureChange => {
1024 RecommendationType::DataStructureChange
1025 }
1026 crate::core::types::RecommendationType::CachingStrategy => {
1027 RecommendationType::CachingStrategy
1028 }
1029 crate::core::types::RecommendationType::MemoryPooling => {
1030 RecommendationType::MemoryPooling
1031 }
1032 crate::core::types::RecommendationType::LazyInitialization => {
1033 RecommendationType::LazyInitialization
1034 }
1035 crate::core::types::RecommendationType::Inlining => {
1036 RecommendationType::Inlining
1037 }
1038 crate::core::types::RecommendationType::Vectorization => {
1039 RecommendationType::Vectorization
1040 }
1041 crate::core::types::RecommendationType::Parallelization => {
1042 RecommendationType::Parallelization
1043 }
1044 },
1045 priority: match r.priority {
1046 crate::core::types::Priority::Low => Priority::Low,
1047 crate::core::types::Priority::Medium => Priority::Medium,
1048 crate::core::types::Priority::High => Priority::High,
1049 crate::core::types::Priority::Critical => Priority::Critical,
1050 },
1051 description: r.description,
1052 expected_improvement: r.expected_improvement,
1053 implementation_difficulty: match r.implementation_difficulty {
1054 crate::core::types::ImplementationDifficulty::Easy => {
1055 ImplementationDifficulty::Easy
1056 }
1057 crate::core::types::ImplementationDifficulty::Medium => {
1058 ImplementationDifficulty::Medium
1059 }
1060 crate::core::types::ImplementationDifficulty::Hard => {
1061 ImplementationDifficulty::Hard
1062 }
1063 crate::core::types::ImplementationDifficulty::VeryHard => {
1064 ImplementationDifficulty::VeryHard
1065 }
1066 },
1067 })
1068 .collect(),
1069 },
1070 }
1071 }
1072}
1073
1074#[cfg(test)]
1075mod tests {
1076 use super::*;
1077
1078 #[test]
1079 fn test_allocation_info_creation() {
1080 let info = AllocationInfo::new(0x12345678, 1024);
1081
1082 assert_eq!(info.ptr, 0x12345678);
1083 assert_eq!(info.size, 1024);
1084 assert!(info.is_active());
1085 assert!(info.borrow_info.is_none());
1086 assert!(info.clone_info.is_some());
1087 assert!(!info.ownership_history_available);
1088 }
1089
1090 #[test]
1091 fn test_allocation_info_mark_deallocated() {
1092 let mut info = AllocationInfo::new(0x1000, 512);
1093 assert!(info.is_active());
1094
1095 info.mark_deallocated();
1096 assert!(!info.is_active());
1097 assert!(info.timestamp_dealloc.is_some());
1098 }
1099
1100 #[test]
1101 fn test_allocation_info_enhance_with_type_info() {
1102 let mut info = AllocationInfo::new(0x1000, 512);
1103
1104 info.enhance_with_type_info("std::rc::Rc<String>");
1106 if let Some(clone_info) = &info.clone_info {
1107 assert_eq!(clone_info.clone_count, 2);
1108 }
1109
1110 info.enhance_with_type_info("Vec<i32>");
1112 if let Some(borrow_info) = &info.borrow_info {
1113 assert_eq!(borrow_info.immutable_borrows, 4);
1114 assert_eq!(borrow_info.mutable_borrows, 2);
1115 }
1116 }
1117
1118 #[test]
1119 fn test_borrow_info_default() {
1120 let borrow_info = BorrowInfo::default();
1121
1122 assert_eq!(borrow_info.immutable_borrows, 0);
1123 assert_eq!(borrow_info.mutable_borrows, 0);
1124 assert_eq!(borrow_info.max_concurrent_borrows, 0);
1125 assert_eq!(borrow_info.last_borrow_timestamp, None);
1126 }
1127
1128 #[test]
1129 fn test_clone_info_default() {
1130 let clone_info = CloneInfo::default();
1131
1132 assert_eq!(clone_info.clone_count, 0);
1133 assert!(!clone_info.is_clone);
1134 assert_eq!(clone_info.original_ptr, None);
1135 }
1136
1137 #[test]
1138 fn test_allocation_info_serialization() {
1139 let info = AllocationInfo::new(0x1000, 512);
1140
1141 let serialized = serde_json::to_string(&info);
1143 assert!(serialized.is_ok());
1144
1145 let json_str = serialized.expect("Failed to serialize AllocationInfo to JSON");
1147 assert!(json_str.contains("ptr"));
1148 assert!(json_str.contains("size"));
1149 }
1150}