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 generic_info: Option<GenericTypeInfo>,
112 pub dynamic_type_info: Option<DynamicTypeInfo>,
114 pub runtime_state: Option<RuntimeStateInfo>,
116 pub stack_allocation: Option<StackAllocationInfo>,
118 pub temporary_object: Option<TemporaryObjectInfo>,
120 pub fragmentation_analysis: Option<EnhancedFragmentationAnalysis>,
122 pub generic_instantiation: Option<GenericInstantiationInfo>,
124 pub type_relationships: Option<TypeRelationshipInfo>,
126 pub type_usage: Option<TypeUsageInfo>,
128 pub function_call_tracking: Option<FunctionCallTrackingInfo>,
130 pub lifecycle_tracking: Option<ObjectLifecycleInfo>,
132 pub access_tracking: Option<MemoryAccessTrackingInfo>,
134 pub drop_chain_analysis: Option<DropChainAnalysis>,
136}
137
138impl From<crate::core::types::AllocationInfo> for AllocationInfo {
139 fn from(old: crate::core::types::AllocationInfo) -> Self {
140 let thread_id = thread::current().id();
143
144 let borrow_info = old.borrow_info.map(|b| BorrowInfo {
146 immutable_borrows: b.immutable_borrows,
147 mutable_borrows: b.mutable_borrows,
148 max_concurrent_borrows: b.max_concurrent_borrows,
149 last_borrow_timestamp: b.last_borrow_timestamp,
150 _source: None,
151 _confidence: None,
152 });
153
154 let clone_info = old.clone_info.map(|c| CloneInfo {
156 clone_count: c.clone_count,
157 is_clone: c.is_clone,
158 original_ptr: c.original_ptr,
159 _source: None,
160 _confidence: None,
161 });
162
163 let smart_pointer_info =
166 old.smart_pointer_info
167 .map(|s| super::smart_pointer::SmartPointerInfo {
168 data_ptr: s.data_ptr,
169 cloned_from: s.cloned_from,
170 clones: s.clones,
171 ref_count_history: s
172 .ref_count_history
173 .iter()
174 .map(|r| super::smart_pointer::RefCountSnapshot {
175 timestamp: r.timestamp,
176 strong_count: r.strong_count,
177 weak_count: r.weak_count,
178 })
179 .collect(),
180 weak_count: s.weak_count,
181 is_weak_reference: s.is_weak_reference,
182 is_data_owner: s.is_data_owner,
183 is_implicitly_deallocated: s.is_implicitly_deallocated,
184 pointer_type: match s.pointer_type {
185 crate::core::types::SmartPointerType::Rc => {
186 super::smart_pointer::SmartPointerType::Rc
187 }
188 crate::core::types::SmartPointerType::Arc => {
189 super::smart_pointer::SmartPointerType::Arc
190 }
191 crate::core::types::SmartPointerType::RcWeak => {
192 super::smart_pointer::SmartPointerType::RcWeak
193 }
194 crate::core::types::SmartPointerType::ArcWeak => {
195 super::smart_pointer::SmartPointerType::ArcWeak
196 }
197 crate::core::types::SmartPointerType::Box => {
198 super::smart_pointer::SmartPointerType::Box
199 }
200 },
201 });
202
203 Self {
204 ptr: old.ptr,
205 size: old.size,
206 var_name: old.var_name,
207 type_name: old.type_name,
208 scope_name: old.scope_name,
209 timestamp_alloc: old.timestamp_alloc,
210 timestamp_dealloc: old.timestamp_dealloc,
211 thread_id,
212 thread_id_u64: old.thread_id.parse().unwrap_or_else(|_| {
213 tracing::warn!(
214 "Failed to parse thread_id: '{}', defaulting to 0",
215 old.thread_id
216 );
217 0
218 }),
219 borrow_count: old.borrow_count,
220 stack_trace: old.stack_trace,
221 is_leaked: old.is_leaked,
222 lifetime_ms: old.lifetime_ms,
223 borrow_info,
224 clone_info,
225 ownership_history_available: old.ownership_history_available,
226 smart_pointer_info,
227 memory_layout: old.memory_layout.map(Into::into),
229 generic_info: old.generic_info.map(Into::into),
230 dynamic_type_info: old.dynamic_type_info.map(Into::into),
231 runtime_state: old.runtime_state.map(Into::into),
232 stack_allocation: old.stack_allocation.map(Into::into),
233 temporary_object: old.temporary_object.map(Into::into),
234 fragmentation_analysis: old.fragmentation_analysis.map(Into::into),
235 generic_instantiation: old.generic_instantiation.map(Into::into),
236 type_relationships: old.type_relationships.map(Into::into),
237 type_usage: old.type_usage.map(Into::into),
238 function_call_tracking: old.function_call_tracking.map(Into::into),
239 lifecycle_tracking: old.lifecycle_tracking.map(Into::into),
240 access_tracking: old.access_tracking.map(Into::into),
241 drop_chain_analysis: old.drop_chain_analysis.map(Into::into),
242 }
243 }
244}
245
246impl From<crate::capture::backends::core_types::AllocationInfo> for AllocationInfo {
247 fn from(info: crate::capture::backends::core_types::AllocationInfo) -> Self {
248 Self {
249 ptr: info.ptr,
250 size: info.size,
251 var_name: info.var_name,
252 type_name: info.type_name,
253 scope_name: None,
254 timestamp_alloc: info.allocated_at_ns,
255 timestamp_dealloc: None,
256 thread_id: std::thread::current().id(),
257 thread_id_u64: info.thread_id,
258 borrow_count: 0,
259 stack_trace: info.stack_trace,
260 is_leaked: false,
261 lifetime_ms: None,
262 borrow_info: None,
263 clone_info: None,
264 ownership_history_available: false,
265 smart_pointer_info: None,
266 memory_layout: None,
267 generic_info: None,
268 dynamic_type_info: None,
269 runtime_state: None,
270 stack_allocation: None,
271 temporary_object: None,
272 fragmentation_analysis: None,
273 generic_instantiation: None,
274 type_relationships: None,
275 type_usage: None,
276 function_call_tracking: None,
277 lifecycle_tracking: None,
278 access_tracking: None,
279 drop_chain_analysis: None,
280 }
281 }
282}
283
284#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
286pub struct TypeUsageInfo {
287 pub type_name: String,
289 pub total_usage_count: u64,
291 pub usage_contexts: Vec<UsageContext>,
293 pub usage_timeline: Vec<UsageTimePoint>,
295 pub hot_paths: Vec<HotPath>,
297 pub performance_impact: TypePerformanceImpact,
299}
300
301#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
303pub struct UsageContext {
304 pub context_type: ContextType,
306 pub location: String,
308 pub frequency: u32,
310 pub performance_metrics: ContextPerformanceMetrics,
312}
313
314#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
316pub enum ContextType {
317 FunctionParameter,
319 FunctionReturn,
321 LocalVariable,
323 StructField,
325 EnumVariant,
327 TraitMethod,
329 GenericConstraint,
331 ClosureCapture,
333 AsyncContext,
335 UnsafeContext,
337}
338
339#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
341pub struct ContextPerformanceMetrics {
342 pub avg_execution_time_ns: f64,
344 pub allocation_frequency: f64,
346 pub cache_miss_rate: f64,
348 pub branch_misprediction_rate: f64,
350}
351
352#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
354pub struct UsageTimePoint {
355 pub timestamp: u64,
357 pub usage_count: u32,
359 pub memory_usage: usize,
361 pub performance_snapshot: PerformanceSnapshot,
363}
364
365#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
367pub struct PerformanceSnapshot {
368 pub cpu_usage: f64,
370 pub memory_usage: f64,
372 pub cache_hit_rate: f64,
374 pub throughput: f64,
376}
377
378#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
380pub struct HotPath {
381 pub path_id: String,
383 pub call_sequence: Vec<String>,
385 pub execution_frequency: u64,
387 pub total_execution_time_ns: u64,
389 pub avg_execution_time_ns: f64,
391 pub memory_allocations: u32,
393 pub bottlenecks: Vec<PerformanceBottleneck>,
395}
396
397#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
399pub struct PerformanceBottleneck {
400 pub bottleneck_type: BottleneckType,
402 pub location: String,
404 pub severity: ImpactLevel,
406 pub description: String,
408 pub optimization_suggestion: String,
410}
411
412#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
414pub enum BottleneckType {
415 MemoryAllocation,
417 MemoryDeallocation,
419 CacheMiss,
421 BranchMisprediction,
423 FunctionCall,
425 DataMovement,
427 Synchronization,
429 IO,
431}
432
433#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
435pub enum ImpactLevel {
436 Low,
438 Medium,
440 High,
442 Critical,
444}
445
446#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
448pub struct TypePerformanceImpact {
449 pub performance_score: f64,
451 pub memory_efficiency_score: f64,
453 pub cpu_efficiency_score: f64,
455 pub cache_efficiency_score: f64,
457 pub optimization_recommendations: Vec<OptimizationRecommendation>,
459}
460
461#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
463pub struct OptimizationRecommendation {
464 pub recommendation_type: RecommendationType,
466 pub priority: Priority,
468 pub description: String,
470 pub expected_improvement: f64,
472 pub implementation_difficulty: ImplementationDifficulty,
474}
475
476#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
478pub enum RecommendationType {
479 MemoryLayout,
481 AlgorithmChange,
483 DataStructureChange,
485 CachingStrategy,
487 MemoryPooling,
489 LazyInitialization,
491 Inlining,
493 Vectorization,
495 Parallelization,
497}
498
499#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
501pub enum Priority {
502 Low,
504 Medium,
506 High,
508 Critical,
510}
511
512#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
514pub enum ImplementationDifficulty {
515 Easy,
517 Medium,
519 Hard,
521 VeryHard,
523}
524
525impl Serialize for AllocationInfo {
527 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
528 where
529 S: serde::Serializer,
530 {
531 use serde::ser::SerializeStruct;
532 let mut state = serializer.serialize_struct("AllocationInfo", 25)?;
533 state.serialize_field("ptr", &self.ptr)?;
534 state.serialize_field("size", &self.size)?;
535 state.serialize_field("var_name", &self.var_name)?;
536 state.serialize_field("type_name", &self.type_name)?;
537 state.serialize_field("scope_name", &self.scope_name)?;
538 state.serialize_field("timestamp_alloc", &self.timestamp_alloc)?;
539 state.serialize_field("timestamp_dealloc", &self.timestamp_dealloc)?;
540 state.serialize_field("thread_id", &format!("{:?}", self.thread_id))?;
541 state.serialize_field("borrow_count", &self.borrow_count)?;
542 state.serialize_field("stack_trace", &self.stack_trace)?;
543 state.serialize_field("is_leaked", &self.is_leaked)?;
544 state.serialize_field("lifetime_ms", &self.lifetime_ms)?;
545 state.serialize_field("borrow_info", &self.borrow_info)?;
546 state.serialize_field("clone_info", &self.clone_info)?;
547 state.serialize_field(
548 "ownership_history_available",
549 &self.ownership_history_available,
550 )?;
551 state.serialize_field("smart_pointer_info", &self.smart_pointer_info)?;
552 state.serialize_field("memory_layout", &self.memory_layout)?;
553 state.serialize_field("generic_info", &self.generic_info)?;
554 state.serialize_field("dynamic_type_info", &self.dynamic_type_info)?;
555 state.serialize_field("runtime_state", &self.runtime_state)?;
556 state.serialize_field("stack_allocation", &self.stack_allocation)?;
557 state.serialize_field("temporary_object", &self.temporary_object)?;
558 state.serialize_field("fragmentation_analysis", &self.fragmentation_analysis)?;
559 state.serialize_field("generic_instantiation", &self.generic_instantiation)?;
560 state.serialize_field("type_relationships", &self.type_relationships)?;
561 state.serialize_field("type_usage", &self.type_usage)?;
562 state.serialize_field("function_call_tracking", &self.function_call_tracking)?;
563 state.serialize_field("lifecycle_tracking", &self.lifecycle_tracking)?;
564 state.serialize_field("access_tracking", &self.access_tracking)?;
565 state.serialize_field("drop_chain_analysis", &self.drop_chain_analysis)?;
566 state.end()
567 }
568}
569
570impl<'de> Deserialize<'de> for AllocationInfo {
572 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
573 where
574 D: serde::Deserializer<'de>,
575 {
576 #[derive(Deserialize)]
577 struct AllocationInfoHelper {
578 ptr: usize,
579 size: usize,
580 var_name: Option<String>,
581 type_name: Option<String>,
582 scope_name: Option<String>,
583 timestamp_alloc: u64,
584 timestamp_dealloc: Option<u64>,
585 #[serde(default)]
586 thread_id: String,
587 #[serde(default)]
588 thread_id_u64: u64,
589 borrow_count: usize,
590 stack_trace: Option<Vec<String>>,
591 is_leaked: bool,
592 lifetime_ms: Option<u64>,
593 borrow_info: Option<BorrowInfo>,
594 clone_info: Option<CloneInfo>,
595 ownership_history_available: Option<bool>,
596 smart_pointer_info: Option<SmartPointerInfo>,
597 memory_layout: Option<MemoryLayoutInfo>,
598 generic_info: Option<GenericTypeInfo>,
599 dynamic_type_info: Option<DynamicTypeInfo>,
600 runtime_state: Option<RuntimeStateInfo>,
601 stack_allocation: Option<StackAllocationInfo>,
602 temporary_object: Option<TemporaryObjectInfo>,
603 fragmentation_analysis: Option<EnhancedFragmentationAnalysis>,
604 generic_instantiation: Option<GenericInstantiationInfo>,
605 type_relationships: Option<TypeRelationshipInfo>,
606 type_usage: Option<TypeUsageInfo>,
607 function_call_tracking: Option<FunctionCallTrackingInfo>,
608 lifecycle_tracking: Option<ObjectLifecycleInfo>,
609 access_tracking: Option<MemoryAccessTrackingInfo>,
610 drop_chain_analysis: Option<DropChainAnalysis>,
611 }
612
613 let helper = AllocationInfoHelper::deserialize(deserializer)?;
614 let thread_id = if !helper.thread_id.is_empty() {
616 thread::current().id()
619 } else {
620 thread::current().id()
621 };
622
623 Ok(AllocationInfo {
624 ptr: helper.ptr,
625 size: helper.size,
626 var_name: helper.var_name,
627 type_name: helper.type_name,
628 scope_name: helper.scope_name,
629 timestamp_alloc: helper.timestamp_alloc,
630 timestamp_dealloc: helper.timestamp_dealloc,
631 thread_id,
632 thread_id_u64: helper.thread_id_u64,
633 borrow_count: helper.borrow_count,
634 stack_trace: helper.stack_trace,
635 is_leaked: helper.is_leaked,
636 lifetime_ms: helper.lifetime_ms,
637 borrow_info: helper.borrow_info,
638 clone_info: helper.clone_info,
639 ownership_history_available: helper.ownership_history_available.unwrap_or(false),
640 smart_pointer_info: helper.smart_pointer_info,
641 memory_layout: helper.memory_layout,
642 generic_info: helper.generic_info,
643 dynamic_type_info: helper.dynamic_type_info,
644 runtime_state: helper.runtime_state,
645 stack_allocation: helper.stack_allocation,
646 temporary_object: helper.temporary_object,
647 fragmentation_analysis: helper.fragmentation_analysis,
648 generic_instantiation: helper.generic_instantiation,
649 type_relationships: helper.type_relationships,
650 type_usage: helper.type_usage,
651 function_call_tracking: helper.function_call_tracking,
652 lifecycle_tracking: helper.lifecycle_tracking,
653 access_tracking: helper.access_tracking,
654 drop_chain_analysis: helper.drop_chain_analysis,
655 })
656 }
657}
658
659impl AllocationInfo {
660 pub fn new(ptr: usize, size: usize) -> Self {
678 let timestamp = std::time::SystemTime::now()
679 .duration_since(std::time::UNIX_EPOCH)
680 .unwrap_or_default()
681 .as_nanos() as u64;
682
683 Self {
684 ptr,
685 size,
686 var_name: None,
687 type_name: None,
688 scope_name: None,
689 timestamp_alloc: timestamp,
690 timestamp_dealloc: None,
691 thread_id: thread::current().id(),
692 thread_id_u64: {
693 use std::hash::{Hash, Hasher};
694 let mut hasher = std::collections::hash_map::DefaultHasher::new();
695 thread::current().id().hash(&mut hasher);
696 hasher.finish()
697 },
698 borrow_count: 0,
699 stack_trace: None,
700 is_leaked: false,
701 lifetime_ms: Some(1), borrow_info: None, clone_info: Some(CloneInfo {
704 clone_count: 0,
705 is_clone: false,
706 original_ptr: None,
707 _source: None,
708 _confidence: None,
709 }),
710 ownership_history_available: false, smart_pointer_info: None,
712 memory_layout: None,
713 generic_info: None,
714 dynamic_type_info: None,
715 runtime_state: None,
716 stack_allocation: None,
717 temporary_object: None,
718 fragmentation_analysis: None,
719 generic_instantiation: None,
720 type_relationships: None,
721 type_usage: None,
722 function_call_tracking: None,
723 lifecycle_tracking: None,
724 access_tracking: None,
725 drop_chain_analysis: None,
726 }
727 }
728
729 pub fn set_source_location(&mut self, file: &str, line: u32) {
731 let frame = format!("{}:{}", file, line);
732 self.stack_trace.get_or_insert_with(Vec::new).push(frame);
733 }
734
735 pub fn set_smart_pointer_info(&mut self, info: SmartPointerInfo) {
737 self.smart_pointer_info = Some(info);
738 }
739
740 pub fn mark_deallocated(&mut self) {
742 self.timestamp_dealloc = Some(
743 std::time::SystemTime::now()
744 .duration_since(std::time::UNIX_EPOCH)
745 .unwrap_or_default()
746 .as_nanos() as u64,
747 );
748 }
749
750 pub fn is_active(&self) -> bool {
752 self.timestamp_dealloc.is_none()
753 }
754
755 pub fn enhance_with_type_info(&mut self, type_name: &str) {
762 if self.timestamp_dealloc.is_none() {
763 let current_time = std::time::SystemTime::now()
764 .duration_since(std::time::UNIX_EPOCH)
765 .unwrap_or_default()
766 .as_nanos() as u64;
767 let elapsed_ns = current_time.saturating_sub(self.timestamp_alloc);
768 let elapsed_ms = elapsed_ns / 1_000_000;
769 self.lifetime_ms = Some(if elapsed_ms == 0 { 1 } else { elapsed_ms });
770 }
771
772 if type_name.contains("Rc<") || type_name.contains("Arc<") {
775 self.clone_info = Some(CloneInfo {
776 clone_count: 2,
777 is_clone: false,
778 original_ptr: None,
779 _source: Some("inferred".to_string()),
780 _confidence: Some("low".to_string()),
781 });
782
783 self.borrow_info = Some(BorrowInfo {
784 immutable_borrows: 5,
785 mutable_borrows: 0,
786 max_concurrent_borrows: 5,
787 last_borrow_timestamp: Some(self.timestamp_alloc + 1000000),
788 _source: Some("inferred".to_string()),
789 _confidence: Some("low".to_string()),
790 });
791 } else if type_name.contains("Vec<")
792 || type_name.contains("String")
793 || type_name.contains("HashMap")
794 {
795 self.borrow_info = Some(BorrowInfo {
796 immutable_borrows: 4,
797 mutable_borrows: 2,
798 max_concurrent_borrows: 3,
799 last_borrow_timestamp: Some(self.timestamp_alloc + 800000),
800 _source: Some("inferred".to_string()),
801 _confidence: Some("low".to_string()),
802 });
803 } else if type_name.contains("Box<") {
804 self.clone_info = Some(CloneInfo {
805 clone_count: 0,
806 is_clone: false,
807 original_ptr: None,
808 _source: Some("inferred".to_string()),
809 _confidence: Some("low".to_string()),
810 });
811
812 self.borrow_info = Some(BorrowInfo {
813 immutable_borrows: 2,
814 mutable_borrows: 1,
815 max_concurrent_borrows: 1,
816 last_borrow_timestamp: Some(self.timestamp_alloc + 300000),
817 _source: Some("inferred".to_string()),
818 _confidence: Some("low".to_string()),
819 });
820 }
821 }
822
823 pub fn enhance_with_inference(&mut self, engine: &crate::capture::inference::InferenceEngine) {
827 let type_name = self.type_name.as_deref();
828
829 let inferred_borrow = engine.infer_borrow_info(type_name);
830 self.borrow_info = Some(BorrowInfo {
831 immutable_borrows: inferred_borrow.immutable_borrows,
832 mutable_borrows: inferred_borrow.mutable_borrows,
833 max_concurrent_borrows: inferred_borrow.max_concurrent_borrows,
834 last_borrow_timestamp: None,
835 _source: Some("inferred".to_string()),
836 _confidence: Some(format!("{:?}", inferred_borrow._confidence).to_lowercase()),
837 });
838
839 let inferred_sp = engine.infer_smart_pointer(type_name);
840 if inferred_sp.pointer_type != crate::capture::inference::SmartPointerType::Unknown {
841 self.clone_info = Some(CloneInfo {
842 clone_count: inferred_sp.ref_count.unwrap_or(0),
843 is_clone: false,
844 original_ptr: None,
845 _source: Some("inferred".to_string()),
846 _confidence: Some(format!("{:?}", inferred_sp._confidence).to_lowercase()),
847 });
848 }
849 }
850}
851
852#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
854pub struct RiskDistribution {
855 pub low_risk: usize,
857 pub medium_risk: usize,
859 pub high_risk: usize,
861 pub critical_risk: usize,
863}
864
865impl From<crate::core::types::TypeUsageInfo> for TypeUsageInfo {
867 fn from(old: crate::core::types::TypeUsageInfo) -> Self {
868 Self {
869 type_name: old.type_name,
870 total_usage_count: old.total_usage_count,
871 usage_contexts: old
872 .usage_contexts
873 .into_iter()
874 .map(|c| UsageContext {
875 context_type: match c.context_type {
876 crate::core::types::ContextType::FunctionParameter => {
877 ContextType::FunctionParameter
878 }
879 crate::core::types::ContextType::FunctionReturn => {
880 ContextType::FunctionReturn
881 }
882 crate::core::types::ContextType::LocalVariable => {
883 ContextType::LocalVariable
884 }
885 crate::core::types::ContextType::StructField => ContextType::StructField,
886 crate::core::types::ContextType::EnumVariant => ContextType::EnumVariant,
887 crate::core::types::ContextType::TraitMethod => ContextType::TraitMethod,
888 crate::core::types::ContextType::GenericConstraint => {
889 ContextType::GenericConstraint
890 }
891 crate::core::types::ContextType::ClosureCapture => {
892 ContextType::ClosureCapture
893 }
894 crate::core::types::ContextType::AsyncContext => ContextType::AsyncContext,
895 crate::core::types::ContextType::UnsafeContext => {
896 ContextType::UnsafeContext
897 }
898 },
899 location: c.location,
900 frequency: c.frequency,
901 performance_metrics: ContextPerformanceMetrics {
902 avg_execution_time_ns: c.performance_metrics.avg_execution_time_ns,
903 allocation_frequency: c.performance_metrics.allocation_frequency,
904 cache_miss_rate: c.performance_metrics.cache_miss_rate,
905 branch_misprediction_rate: c.performance_metrics.branch_misprediction_rate,
906 },
907 })
908 .collect(),
909 usage_timeline: old
910 .usage_timeline
911 .into_iter()
912 .map(|t| UsageTimePoint {
913 timestamp: t.timestamp,
914 usage_count: t.usage_count,
915 memory_usage: t.memory_usage,
916 performance_snapshot: PerformanceSnapshot {
917 cpu_usage: t.performance_snapshot.cpu_usage,
918 memory_usage: t.performance_snapshot.memory_usage,
919 cache_hit_rate: t.performance_snapshot.cache_hit_rate,
920 throughput: t.performance_snapshot.throughput,
921 },
922 })
923 .collect(),
924 hot_paths: old
925 .hot_paths
926 .into_iter()
927 .map(|h| HotPath {
928 path_id: h.path_id,
929 call_sequence: h.call_sequence,
930 execution_frequency: h.execution_frequency,
931 total_execution_time_ns: h.total_execution_time_ns,
932 avg_execution_time_ns: h.avg_execution_time_ns,
933 memory_allocations: h.memory_allocations,
934 bottlenecks: h
935 .bottlenecks
936 .into_iter()
937 .map(|b| PerformanceBottleneck {
938 bottleneck_type: match b.bottleneck_type {
939 crate::core::types::BottleneckType::MemoryAllocation => {
940 BottleneckType::MemoryAllocation
941 }
942 crate::core::types::BottleneckType::MemoryDeallocation => {
943 BottleneckType::MemoryDeallocation
944 }
945 crate::core::types::BottleneckType::CacheMiss => {
946 BottleneckType::CacheMiss
947 }
948 crate::core::types::BottleneckType::BranchMisprediction => {
949 BottleneckType::BranchMisprediction
950 }
951 crate::core::types::BottleneckType::FunctionCall => {
952 BottleneckType::FunctionCall
953 }
954 crate::core::types::BottleneckType::DataMovement => {
955 BottleneckType::DataMovement
956 }
957 crate::core::types::BottleneckType::Synchronization => {
958 BottleneckType::Synchronization
959 }
960 crate::core::types::BottleneckType::IO => BottleneckType::IO,
961 },
962 location: b.location,
963 severity: match b.severity {
964 crate::core::types::ImpactLevel::Low => ImpactLevel::Low,
965 crate::core::types::ImpactLevel::Medium => ImpactLevel::Medium,
966 crate::core::types::ImpactLevel::High => ImpactLevel::High,
967 crate::core::types::ImpactLevel::Critical => ImpactLevel::Critical,
968 },
969 description: b.description,
970 optimization_suggestion: b.optimization_suggestion,
971 })
972 .collect(),
973 })
974 .collect(),
975 performance_impact: TypePerformanceImpact {
976 performance_score: old.performance_impact.performance_score,
977 memory_efficiency_score: old.performance_impact.memory_efficiency_score,
978 cpu_efficiency_score: old.performance_impact.cpu_efficiency_score,
979 cache_efficiency_score: old.performance_impact.cache_efficiency_score,
980 optimization_recommendations: old
981 .performance_impact
982 .optimization_recommendations
983 .into_iter()
984 .map(|r| OptimizationRecommendation {
985 recommendation_type: match r.recommendation_type {
986 crate::core::types::RecommendationType::MemoryLayout => {
987 RecommendationType::MemoryLayout
988 }
989 crate::core::types::RecommendationType::AlgorithmChange => {
990 RecommendationType::AlgorithmChange
991 }
992 crate::core::types::RecommendationType::DataStructureChange => {
993 RecommendationType::DataStructureChange
994 }
995 crate::core::types::RecommendationType::CachingStrategy => {
996 RecommendationType::CachingStrategy
997 }
998 crate::core::types::RecommendationType::MemoryPooling => {
999 RecommendationType::MemoryPooling
1000 }
1001 crate::core::types::RecommendationType::LazyInitialization => {
1002 RecommendationType::LazyInitialization
1003 }
1004 crate::core::types::RecommendationType::Inlining => {
1005 RecommendationType::Inlining
1006 }
1007 crate::core::types::RecommendationType::Vectorization => {
1008 RecommendationType::Vectorization
1009 }
1010 crate::core::types::RecommendationType::Parallelization => {
1011 RecommendationType::Parallelization
1012 }
1013 },
1014 priority: match r.priority {
1015 crate::core::types::Priority::Low => Priority::Low,
1016 crate::core::types::Priority::Medium => Priority::Medium,
1017 crate::core::types::Priority::High => Priority::High,
1018 crate::core::types::Priority::Critical => Priority::Critical,
1019 },
1020 description: r.description,
1021 expected_improvement: r.expected_improvement,
1022 implementation_difficulty: match r.implementation_difficulty {
1023 crate::core::types::ImplementationDifficulty::Easy => {
1024 ImplementationDifficulty::Easy
1025 }
1026 crate::core::types::ImplementationDifficulty::Medium => {
1027 ImplementationDifficulty::Medium
1028 }
1029 crate::core::types::ImplementationDifficulty::Hard => {
1030 ImplementationDifficulty::Hard
1031 }
1032 crate::core::types::ImplementationDifficulty::VeryHard => {
1033 ImplementationDifficulty::VeryHard
1034 }
1035 },
1036 })
1037 .collect(),
1038 },
1039 }
1040 }
1041}
1042
1043#[cfg(test)]
1044mod tests {
1045 use super::*;
1046
1047 #[test]
1048 fn test_allocation_info_creation() {
1049 let info = AllocationInfo::new(0x12345678, 1024);
1050
1051 assert_eq!(info.ptr, 0x12345678);
1052 assert_eq!(info.size, 1024);
1053 assert!(info.is_active());
1054 assert!(info.borrow_info.is_none());
1055 assert!(info.clone_info.is_some());
1056 assert!(!info.ownership_history_available);
1057 }
1058
1059 #[test]
1060 fn test_allocation_info_mark_deallocated() {
1061 let mut info = AllocationInfo::new(0x1000, 512);
1062 assert!(info.is_active());
1063
1064 info.mark_deallocated();
1065 assert!(!info.is_active());
1066 assert!(info.timestamp_dealloc.is_some());
1067 }
1068
1069 #[test]
1070 fn test_allocation_info_enhance_with_type_info() {
1071 let mut info = AllocationInfo::new(0x1000, 512);
1072
1073 info.enhance_with_type_info("std::rc::Rc<String>");
1075 if let Some(clone_info) = &info.clone_info {
1076 assert_eq!(clone_info.clone_count, 2);
1077 }
1078
1079 info.enhance_with_type_info("Vec<i32>");
1081 if let Some(borrow_info) = &info.borrow_info {
1082 assert_eq!(borrow_info.immutable_borrows, 4);
1083 assert_eq!(borrow_info.mutable_borrows, 2);
1084 }
1085 }
1086
1087 #[test]
1088 fn test_borrow_info_default() {
1089 let borrow_info = BorrowInfo::default();
1090
1091 assert_eq!(borrow_info.immutable_borrows, 0);
1092 assert_eq!(borrow_info.mutable_borrows, 0);
1093 assert_eq!(borrow_info.max_concurrent_borrows, 0);
1094 assert_eq!(borrow_info.last_borrow_timestamp, None);
1095 }
1096
1097 #[test]
1098 fn test_clone_info_default() {
1099 let clone_info = CloneInfo::default();
1100
1101 assert_eq!(clone_info.clone_count, 0);
1102 assert!(!clone_info.is_clone);
1103 assert_eq!(clone_info.original_ptr, None);
1104 }
1105
1106 #[test]
1107 fn test_allocation_info_serialization() {
1108 let info = AllocationInfo::new(0x1000, 512);
1109
1110 let serialized = serde_json::to_string(&info);
1112 assert!(serialized.is_ok());
1113
1114 let json_str = serialized.expect("Failed to serialize AllocationInfo to JSON");
1116 assert!(json_str.contains("ptr"));
1117 assert!(json_str.contains("size"));
1118 }
1119}