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