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)]
78pub struct AllocationInfo {
79 pub ptr: usize,
81 pub size: usize,
83 pub var_name: Option<String>,
85 pub type_name: Option<String>,
87 pub scope_name: Option<String>,
89 pub timestamp_alloc: u64,
91 pub timestamp_dealloc: Option<u64>,
93 pub thread_id: thread::ThreadId,
95 pub thread_id_u64: u64,
97 pub borrow_count: usize,
99 pub stack_trace: Option<Vec<String>>,
101 pub is_leaked: bool,
103 pub lifetime_ms: Option<u64>,
105 pub borrow_info: Option<BorrowInfo>,
107 pub clone_info: Option<CloneInfo>,
109 pub ownership_history_available: bool,
111 pub smart_pointer_info: Option<SmartPointerInfo>,
113 pub memory_layout: Option<MemoryLayoutInfo>,
115 pub module_path: Option<String>,
117 pub stack_ptr: Option<usize>,
119 pub generation_id: usize,
121 pub task_id: Option<u64>,
123 pub generic_info: Option<GenericTypeInfo>,
125 pub dynamic_type_info: Option<DynamicTypeInfo>,
127 pub runtime_state: Option<RuntimeStateInfo>,
129 pub stack_allocation: Option<StackAllocationInfo>,
131 pub temporary_object: Option<TemporaryObjectInfo>,
133 pub fragmentation_analysis: Option<EnhancedFragmentationAnalysis>,
135 pub generic_instantiation: Option<GenericInstantiationInfo>,
137 pub type_relationships: Option<TypeRelationshipInfo>,
139 pub type_usage: Option<TypeUsageInfo>,
141 pub function_call_tracking: Option<FunctionCallTrackingInfo>,
143 pub lifecycle_tracking: Option<ObjectLifecycleInfo>,
145 pub access_tracking: Option<MemoryAccessTrackingInfo>,
147 pub drop_chain_analysis: Option<DropChainAnalysis>,
149}
150
151impl From<crate::core::types::AllocationInfo> for AllocationInfo {
152 fn from(old: crate::core::types::AllocationInfo) -> Self {
153 let thread_id = thread::current().id();
156
157 let borrow_info = old.borrow_info.map(|b| BorrowInfo {
159 immutable_borrows: b.immutable_borrows,
160 mutable_borrows: b.mutable_borrows,
161 max_concurrent_borrows: b.max_concurrent_borrows,
162 last_borrow_timestamp: b.last_borrow_timestamp,
163 _source: None,
164 _confidence: None,
165 });
166
167 let clone_info = old.clone_info.map(|c| CloneInfo {
169 clone_count: c.clone_count,
170 is_clone: c.is_clone,
171 original_ptr: c.original_ptr,
172 _source: None,
173 _confidence: None,
174 });
175
176 let smart_pointer_info =
179 old.smart_pointer_info
180 .map(|s| super::smart_pointer::SmartPointerInfo {
181 data_ptr: s.data_ptr,
182 cloned_from: s.cloned_from,
183 clones: s.clones,
184 ref_count_history: s
185 .ref_count_history
186 .iter()
187 .map(|r| super::smart_pointer::RefCountSnapshot {
188 timestamp: r.timestamp,
189 strong_count: r.strong_count,
190 weak_count: r.weak_count,
191 })
192 .collect(),
193 weak_count: s.weak_count,
194 is_weak_reference: s.is_weak_reference,
195 is_data_owner: s.is_data_owner,
196 is_implicitly_deallocated: s.is_implicitly_deallocated,
197 pointer_type: match s.pointer_type {
198 crate::core::types::SmartPointerType::Rc => {
199 super::smart_pointer::SmartPointerType::Rc
200 }
201 crate::core::types::SmartPointerType::Arc => {
202 super::smart_pointer::SmartPointerType::Arc
203 }
204 crate::core::types::SmartPointerType::RcWeak => {
205 super::smart_pointer::SmartPointerType::RcWeak
206 }
207 crate::core::types::SmartPointerType::ArcWeak => {
208 super::smart_pointer::SmartPointerType::ArcWeak
209 }
210 crate::core::types::SmartPointerType::Box => {
211 super::smart_pointer::SmartPointerType::Box
212 }
213 },
214 });
215
216 Self {
217 ptr: old.ptr,
218 size: old.size,
219 var_name: old.var_name,
220 type_name: old.type_name,
221 scope_name: old.scope_name,
222 timestamp_alloc: old.timestamp_alloc,
223 timestamp_dealloc: old.timestamp_dealloc,
224 thread_id,
225 thread_id_u64: old.thread_id.parse().unwrap_or_else(|_| {
226 tracing::warn!(
227 "Failed to parse thread_id: '{}', defaulting to 0",
228 old.thread_id
229 );
230 0
231 }),
232 borrow_count: old.borrow_count,
233 stack_trace: old.stack_trace,
234 is_leaked: old.is_leaked,
235 lifetime_ms: old.lifetime_ms,
236 borrow_info,
237 clone_info,
238 ownership_history_available: old.ownership_history_available,
239 smart_pointer_info,
240 memory_layout: old.memory_layout.map(Into::into),
242 generic_info: old.generic_info.map(Into::into),
243 dynamic_type_info: old.dynamic_type_info.map(Into::into),
244 runtime_state: old.runtime_state.map(Into::into),
245 stack_allocation: old.stack_allocation.map(Into::into),
246 temporary_object: old.temporary_object.map(Into::into),
247 fragmentation_analysis: old.fragmentation_analysis.map(Into::into),
248 generic_instantiation: old.generic_instantiation.map(Into::into),
249 type_relationships: old.type_relationships.map(Into::into),
250 type_usage: old.type_usage.map(Into::into),
251 function_call_tracking: old.function_call_tracking.map(Into::into),
252 lifecycle_tracking: old.lifecycle_tracking.map(Into::into),
253 access_tracking: old.access_tracking.map(Into::into),
254 drop_chain_analysis: old.drop_chain_analysis.map(Into::into),
255 module_path: None, stack_ptr: None,
257 task_id: None,
258 generation_id: 0, }
260 }
261}
262
263impl From<crate::capture::backends::core_types::AllocationInfo> for AllocationInfo {
264 fn from(info: crate::capture::backends::core_types::AllocationInfo) -> Self {
265 Self {
266 ptr: info.ptr,
267 size: info.size,
268 var_name: info.var_name,
269 type_name: info.type_name,
270 scope_name: None,
271 timestamp_alloc: info.allocated_at_ns,
272 timestamp_dealloc: None,
273 thread_id: std::thread::current().id(),
274 thread_id_u64: info.thread_id,
275 borrow_count: 0,
276 stack_trace: info.stack_trace,
277 is_leaked: false,
278 lifetime_ms: None,
279 module_path: None,
280 borrow_info: None,
281 clone_info: None,
282 ownership_history_available: false,
283 smart_pointer_info: None,
284 memory_layout: None,
285 generic_info: None,
286 dynamic_type_info: None,
287 runtime_state: None,
288 stack_allocation: None,
289 temporary_object: None,
290 fragmentation_analysis: None,
291 generic_instantiation: None,
292 type_relationships: None,
293 type_usage: None,
294 function_call_tracking: None,
295 lifecycle_tracking: None,
296 access_tracking: None,
297 drop_chain_analysis: None,
298 stack_ptr: None,
299 task_id: None,
300 generation_id: 0,
301 }
302 }
303}
304
305#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
307pub struct TypeUsageInfo {
308 pub type_name: String,
310 pub total_usage_count: u64,
312 pub usage_contexts: Vec<UsageContext>,
314 pub usage_timeline: Vec<UsageTimePoint>,
316 pub hot_paths: Vec<HotPath>,
318 pub performance_impact: TypePerformanceImpact,
320}
321
322#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
324pub struct UsageContext {
325 pub context_type: ContextType,
327 pub location: String,
329 pub frequency: u32,
331 pub performance_metrics: ContextPerformanceMetrics,
333}
334
335#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
337pub enum ContextType {
338 FunctionParameter,
340 FunctionReturn,
342 LocalVariable,
344 StructField,
346 EnumVariant,
348 TraitMethod,
350 GenericConstraint,
352 ClosureCapture,
354 AsyncContext,
356 UnsafeContext,
358}
359
360#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
362pub struct ContextPerformanceMetrics {
363 pub avg_execution_time_ns: f64,
365 pub allocation_frequency: f64,
367 pub cache_miss_rate: f64,
369 pub branch_misprediction_rate: f64,
371}
372
373#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
375pub struct UsageTimePoint {
376 pub timestamp: u64,
378 pub usage_count: u32,
380 pub memory_usage: usize,
382 pub performance_snapshot: PerformanceSnapshot,
384}
385
386#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
388pub struct PerformanceSnapshot {
389 pub cpu_usage: f64,
391 pub memory_usage: f64,
393 pub cache_hit_rate: f64,
395 pub throughput: f64,
397}
398
399#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
401pub struct HotPath {
402 pub path_id: String,
404 pub call_sequence: Vec<String>,
406 pub execution_frequency: u64,
408 pub total_execution_time_ns: u64,
410 pub avg_execution_time_ns: f64,
412 pub memory_allocations: u32,
414 pub bottlenecks: Vec<PerformanceBottleneck>,
416}
417
418#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
420pub struct PerformanceBottleneck {
421 pub bottleneck_type: BottleneckType,
423 pub location: String,
425 pub severity: ImpactLevel,
427 pub description: String,
429 pub optimization_suggestion: String,
431}
432
433#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
435pub enum BottleneckType {
436 MemoryAllocation,
438 MemoryDeallocation,
440 CacheMiss,
442 BranchMisprediction,
444 FunctionCall,
446 DataMovement,
448 Synchronization,
450 IO,
452}
453
454#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
456pub enum ImpactLevel {
457 Low,
459 Medium,
461 High,
463 Critical,
465}
466
467#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
469pub struct TypePerformanceImpact {
470 pub performance_score: f64,
472 pub memory_efficiency_score: f64,
474 pub cpu_efficiency_score: f64,
476 pub cache_efficiency_score: f64,
478 pub optimization_recommendations: Vec<OptimizationRecommendation>,
480}
481
482#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
484pub struct OptimizationRecommendation {
485 pub recommendation_type: RecommendationType,
487 pub priority: Priority,
489 pub description: String,
491 pub expected_improvement: f64,
493 pub implementation_difficulty: ImplementationDifficulty,
495}
496
497#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
499pub enum RecommendationType {
500 MemoryLayout,
502 AlgorithmChange,
504 DataStructureChange,
506 CachingStrategy,
508 MemoryPooling,
510 LazyInitialization,
512 Inlining,
514 Vectorization,
516 Parallelization,
518}
519
520#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
522pub enum Priority {
523 Low,
525 Medium,
527 High,
529 Critical,
531}
532
533#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
535pub enum ImplementationDifficulty {
536 Easy,
538 Medium,
540 Hard,
542 VeryHard,
544}
545
546impl Serialize for AllocationInfo {
548 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
549 where
550 S: serde::Serializer,
551 {
552 use serde::ser::SerializeStruct;
553 let mut state = serializer.serialize_struct("AllocationInfo", 32)?;
554 state.serialize_field("ptr", &self.ptr)?;
555 state.serialize_field("size", &self.size)?;
556 state.serialize_field("var_name", &self.var_name)?;
557 state.serialize_field("type_name", &self.type_name)?;
558 state.serialize_field("scope_name", &self.scope_name)?;
559 state.serialize_field("timestamp_alloc", &self.timestamp_alloc)?;
560 state.serialize_field("timestamp_dealloc", &self.timestamp_dealloc)?;
561 state.serialize_field("thread_id", &self.thread_id_u64.to_string())?;
565 state.serialize_field("thread_id_u64", &self.thread_id_u64)?;
566 state.serialize_field("borrow_count", &self.borrow_count)?;
567 state.serialize_field("stack_trace", &self.stack_trace)?;
568 state.serialize_field("is_leaked", &self.is_leaked)?;
569 state.serialize_field("lifetime_ms", &self.lifetime_ms)?;
570 state.serialize_field("borrow_info", &self.borrow_info)?;
571 state.serialize_field("clone_info", &self.clone_info)?;
572 state.serialize_field(
573 "ownership_history_available",
574 &self.ownership_history_available,
575 )?;
576 state.serialize_field("smart_pointer_info", &self.smart_pointer_info)?;
577 state.serialize_field("memory_layout", &self.memory_layout)?;
578 state.serialize_field("generic_info", &self.generic_info)?;
579 state.serialize_field("dynamic_type_info", &self.dynamic_type_info)?;
580 state.serialize_field("runtime_state", &self.runtime_state)?;
581 state.serialize_field("stack_allocation", &self.stack_allocation)?;
582 state.serialize_field("temporary_object", &self.temporary_object)?;
583 state.serialize_field("fragmentation_analysis", &self.fragmentation_analysis)?;
584 state.serialize_field("generic_instantiation", &self.generic_instantiation)?;
585 state.serialize_field("type_relationships", &self.type_relationships)?;
586 state.serialize_field("type_usage", &self.type_usage)?;
587 state.serialize_field("function_call_tracking", &self.function_call_tracking)?;
588 state.serialize_field("lifecycle_tracking", &self.lifecycle_tracking)?;
589 state.serialize_field("access_tracking", &self.access_tracking)?;
590 state.serialize_field("drop_chain_analysis", &self.drop_chain_analysis)?;
591 state.serialize_field("module_path", &self.module_path)?;
592 state.end()
593 }
594}
595
596impl<'de> Deserialize<'de> for AllocationInfo {
598 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
599 where
600 D: serde::Deserializer<'de>,
601 {
602 #[derive(Deserialize)]
603 struct AllocationInfoHelper {
604 ptr: usize,
605 size: usize,
606 var_name: Option<String>,
607 type_name: Option<String>,
608 scope_name: Option<String>,
609 timestamp_alloc: u64,
610 timestamp_dealloc: Option<u64>,
611 #[serde(default)]
612 thread_id: String,
613 #[serde(default)]
614 thread_id_u64: u64,
615 borrow_count: usize,
616 stack_trace: Option<Vec<String>>,
617 is_leaked: bool,
618 lifetime_ms: Option<u64>,
619 borrow_info: Option<BorrowInfo>,
620 clone_info: Option<CloneInfo>,
621 ownership_history_available: Option<bool>,
622 smart_pointer_info: Option<SmartPointerInfo>,
623 memory_layout: Option<MemoryLayoutInfo>,
624 generic_info: Option<GenericTypeInfo>,
625 dynamic_type_info: Option<DynamicTypeInfo>,
626 runtime_state: Option<RuntimeStateInfo>,
627 stack_allocation: Option<StackAllocationInfo>,
628 temporary_object: Option<TemporaryObjectInfo>,
629 fragmentation_analysis: Option<EnhancedFragmentationAnalysis>,
630 generic_instantiation: Option<GenericInstantiationInfo>,
631 type_relationships: Option<TypeRelationshipInfo>,
632 type_usage: Option<TypeUsageInfo>,
633 function_call_tracking: Option<FunctionCallTrackingInfo>,
634 lifecycle_tracking: Option<ObjectLifecycleInfo>,
635 access_tracking: Option<MemoryAccessTrackingInfo>,
636 drop_chain_analysis: Option<DropChainAnalysis>,
637 module_path: Option<String>,
638 #[serde(default)]
639 generation_id: usize,
640 }
641
642 let helper = AllocationInfoHelper::deserialize(deserializer)?;
643 let thread_id = if !helper.thread_id.is_empty() {
645 thread::current().id()
648 } else {
649 thread::current().id()
650 };
651
652 Ok(AllocationInfo {
653 ptr: helper.ptr,
654 size: helper.size,
655 var_name: helper.var_name,
656 type_name: helper.type_name,
657 scope_name: helper.scope_name,
658 timestamp_alloc: helper.timestamp_alloc,
659 timestamp_dealloc: helper.timestamp_dealloc,
660 thread_id,
661 thread_id_u64: helper.thread_id_u64,
662 borrow_count: helper.borrow_count,
663 stack_trace: helper.stack_trace,
664 is_leaked: helper.is_leaked,
665 lifetime_ms: helper.lifetime_ms,
666 borrow_info: helper.borrow_info,
667 clone_info: helper.clone_info,
668 ownership_history_available: helper.ownership_history_available.unwrap_or(false),
669 smart_pointer_info: helper.smart_pointer_info,
670 memory_layout: helper.memory_layout,
671 generic_info: helper.generic_info,
672 dynamic_type_info: helper.dynamic_type_info,
673 runtime_state: helper.runtime_state,
674 stack_allocation: helper.stack_allocation,
675 temporary_object: helper.temporary_object,
676 fragmentation_analysis: helper.fragmentation_analysis,
677 generic_instantiation: helper.generic_instantiation,
678 type_relationships: helper.type_relationships,
679 type_usage: helper.type_usage,
680 function_call_tracking: helper.function_call_tracking,
681 lifecycle_tracking: helper.lifecycle_tracking,
682 access_tracking: helper.access_tracking,
683 drop_chain_analysis: helper.drop_chain_analysis,
684 module_path: helper.module_path,
685 stack_ptr: None,
686 task_id: None,
687 generation_id: helper.generation_id,
688 })
689 }
690}
691
692impl AllocationInfo {
693 pub fn new(ptr: usize, size: usize) -> Self {
715 let timestamp = std::time::SystemTime::now()
716 .duration_since(std::time::UNIX_EPOCH)
717 .unwrap_or_default()
718 .as_nanos() as u64;
719
720 Self {
721 ptr,
722 size,
723 var_name: None,
724 type_name: None,
725 scope_name: None,
726 timestamp_alloc: timestamp,
727 timestamp_dealloc: None,
728 thread_id: thread::current().id(),
729 thread_id_u64: {
730 use std::hash::{Hash, Hasher};
731 let mut hasher = std::collections::hash_map::DefaultHasher::new();
732 thread::current().id().hash(&mut hasher);
733 hasher.finish()
734 },
735 borrow_count: 0,
736 stack_trace: None,
737 is_leaked: false,
738 lifetime_ms: Some(1), borrow_info: None, clone_info: Some(CloneInfo {
741 clone_count: 0,
742 is_clone: false,
743 original_ptr: None,
744 _source: None,
745 _confidence: None,
746 }),
747 ownership_history_available: false, smart_pointer_info: None,
749 memory_layout: None,
750 generic_info: None,
751 dynamic_type_info: None,
752 runtime_state: None,
753 stack_allocation: None,
754 temporary_object: None,
755 fragmentation_analysis: None,
756 generic_instantiation: None,
757 type_relationships: None,
758 type_usage: None,
759 function_call_tracking: None,
760 lifecycle_tracking: None,
761 access_tracking: None,
762 drop_chain_analysis: None,
763 module_path: None,
764 stack_ptr: None,
765 task_id: crate::task_registry::TaskIdRegistry::current_task_id(),
766 generation_id: 0,
767 }
768 }
769
770 pub fn set_source_location(&mut self, file: &str, line: u32) {
772 let frame = format!("{}:{}", file, line);
773 self.stack_trace.get_or_insert_with(Vec::new).push(frame);
774 }
775
776 pub fn set_smart_pointer_info(&mut self, info: SmartPointerInfo) {
778 self.smart_pointer_info = Some(info);
779 }
780
781 pub fn mark_deallocated(&mut self) {
783 self.timestamp_dealloc = Some(
784 std::time::SystemTime::now()
785 .duration_since(std::time::UNIX_EPOCH)
786 .unwrap_or_default()
787 .as_nanos() as u64,
788 );
789 }
790
791 pub fn is_active(&self) -> bool {
793 self.timestamp_dealloc.is_none()
794 }
795
796 pub fn enhance_with_type_info(&mut self, type_name: &str) {
803 if self.timestamp_dealloc.is_none() {
804 let current_time = std::time::SystemTime::now()
805 .duration_since(std::time::UNIX_EPOCH)
806 .unwrap_or_default()
807 .as_nanos() as u64;
808 let elapsed_ns = current_time.saturating_sub(self.timestamp_alloc);
809 let elapsed_ms = elapsed_ns / 1_000_000;
810 self.lifetime_ms = Some(if elapsed_ms == 0 { 1 } else { elapsed_ms });
811 }
812
813 if type_name.contains("Rc<") || type_name.contains("Arc<") {
816 self.clone_info = Some(CloneInfo {
817 clone_count: 2,
818 is_clone: false,
819 original_ptr: None,
820 _source: Some("inferred".to_string()),
821 _confidence: Some("low".to_string()),
822 });
823
824 self.borrow_info = Some(BorrowInfo {
825 immutable_borrows: 5,
826 mutable_borrows: 0,
827 max_concurrent_borrows: 5,
828 last_borrow_timestamp: Some(self.timestamp_alloc + 1000000),
829 _source: Some("inferred".to_string()),
830 _confidence: Some("low".to_string()),
831 });
832 } else if type_name.contains("Vec<")
833 || type_name.contains("String")
834 || type_name.contains("HashMap")
835 {
836 self.borrow_info = Some(BorrowInfo {
837 immutable_borrows: 4,
838 mutable_borrows: 2,
839 max_concurrent_borrows: 3,
840 last_borrow_timestamp: Some(self.timestamp_alloc + 800000),
841 _source: Some("inferred".to_string()),
842 _confidence: Some("low".to_string()),
843 });
844 } else if type_name.contains("Box<") {
845 self.clone_info = Some(CloneInfo {
846 clone_count: 0,
847 is_clone: false,
848 original_ptr: None,
849 _source: Some("inferred".to_string()),
850 _confidence: Some("low".to_string()),
851 });
852
853 self.borrow_info = Some(BorrowInfo {
854 immutable_borrows: 2,
855 mutable_borrows: 1,
856 max_concurrent_borrows: 1,
857 last_borrow_timestamp: Some(self.timestamp_alloc + 300000),
858 _source: Some("inferred".to_string()),
859 _confidence: Some("low".to_string()),
860 });
861 }
862 }
863
864 pub fn enhance_with_inference(&mut self, engine: &crate::capture::inference::InferenceEngine) {
868 let type_name = self.type_name.as_deref();
869
870 let inferred_borrow = engine.infer_borrow_info(type_name);
871 self.borrow_info = Some(BorrowInfo {
872 immutable_borrows: inferred_borrow.immutable_borrows,
873 mutable_borrows: inferred_borrow.mutable_borrows,
874 max_concurrent_borrows: inferred_borrow.max_concurrent_borrows,
875 last_borrow_timestamp: None,
876 _source: Some("inferred".to_string()),
877 _confidence: Some(format!("{:?}", inferred_borrow._confidence).to_lowercase()),
878 });
879
880 let inferred_sp = engine.infer_smart_pointer(type_name);
881 if inferred_sp.pointer_type != crate::capture::inference::SmartPointerType::Unknown {
882 self.clone_info = Some(CloneInfo {
883 clone_count: inferred_sp.ref_count.unwrap_or(0),
884 is_clone: false,
885 original_ptr: None,
886 _source: Some("inferred".to_string()),
887 _confidence: Some(format!("{:?}", inferred_sp._confidence).to_lowercase()),
888 });
889 }
890 }
891}
892
893#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
895pub struct RiskDistribution {
896 pub low_risk: usize,
898 pub medium_risk: usize,
900 pub high_risk: usize,
902 pub critical_risk: usize,
904}
905
906impl From<crate::core::types::TypeUsageInfo> for TypeUsageInfo {
908 fn from(old: crate::core::types::TypeUsageInfo) -> Self {
909 Self {
910 type_name: old.type_name,
911 total_usage_count: old.total_usage_count,
912 usage_contexts: old
913 .usage_contexts
914 .into_iter()
915 .map(|c| UsageContext {
916 context_type: match c.context_type {
917 crate::core::types::ContextType::FunctionParameter => {
918 ContextType::FunctionParameter
919 }
920 crate::core::types::ContextType::FunctionReturn => {
921 ContextType::FunctionReturn
922 }
923 crate::core::types::ContextType::LocalVariable => {
924 ContextType::LocalVariable
925 }
926 crate::core::types::ContextType::StructField => ContextType::StructField,
927 crate::core::types::ContextType::EnumVariant => ContextType::EnumVariant,
928 crate::core::types::ContextType::TraitMethod => ContextType::TraitMethod,
929 crate::core::types::ContextType::GenericConstraint => {
930 ContextType::GenericConstraint
931 }
932 crate::core::types::ContextType::ClosureCapture => {
933 ContextType::ClosureCapture
934 }
935 crate::core::types::ContextType::AsyncContext => ContextType::AsyncContext,
936 crate::core::types::ContextType::UnsafeContext => {
937 ContextType::UnsafeContext
938 }
939 },
940 location: c.location,
941 frequency: c.frequency,
942 performance_metrics: ContextPerformanceMetrics {
943 avg_execution_time_ns: c.performance_metrics.avg_execution_time_ns,
944 allocation_frequency: c.performance_metrics.allocation_frequency,
945 cache_miss_rate: c.performance_metrics.cache_miss_rate,
946 branch_misprediction_rate: c.performance_metrics.branch_misprediction_rate,
947 },
948 })
949 .collect(),
950 usage_timeline: old
951 .usage_timeline
952 .into_iter()
953 .map(|t| UsageTimePoint {
954 timestamp: t.timestamp,
955 usage_count: t.usage_count,
956 memory_usage: t.memory_usage,
957 performance_snapshot: PerformanceSnapshot {
958 cpu_usage: t.performance_snapshot.cpu_usage,
959 memory_usage: t.performance_snapshot.memory_usage,
960 cache_hit_rate: t.performance_snapshot.cache_hit_rate,
961 throughput: t.performance_snapshot.throughput,
962 },
963 })
964 .collect(),
965 hot_paths: old
966 .hot_paths
967 .into_iter()
968 .map(|h| HotPath {
969 path_id: h.path_id,
970 call_sequence: h.call_sequence,
971 execution_frequency: h.execution_frequency,
972 total_execution_time_ns: h.total_execution_time_ns,
973 avg_execution_time_ns: h.avg_execution_time_ns,
974 memory_allocations: h.memory_allocations,
975 bottlenecks: h
976 .bottlenecks
977 .into_iter()
978 .map(|b| PerformanceBottleneck {
979 bottleneck_type: match b.bottleneck_type {
980 crate::core::types::BottleneckType::MemoryAllocation => {
981 BottleneckType::MemoryAllocation
982 }
983 crate::core::types::BottleneckType::MemoryDeallocation => {
984 BottleneckType::MemoryDeallocation
985 }
986 crate::core::types::BottleneckType::CacheMiss => {
987 BottleneckType::CacheMiss
988 }
989 crate::core::types::BottleneckType::BranchMisprediction => {
990 BottleneckType::BranchMisprediction
991 }
992 crate::core::types::BottleneckType::FunctionCall => {
993 BottleneckType::FunctionCall
994 }
995 crate::core::types::BottleneckType::DataMovement => {
996 BottleneckType::DataMovement
997 }
998 crate::core::types::BottleneckType::Synchronization => {
999 BottleneckType::Synchronization
1000 }
1001 crate::core::types::BottleneckType::IO => BottleneckType::IO,
1002 },
1003 location: b.location,
1004 severity: match b.severity {
1005 crate::core::types::ImpactLevel::Low => ImpactLevel::Low,
1006 crate::core::types::ImpactLevel::Medium => ImpactLevel::Medium,
1007 crate::core::types::ImpactLevel::High => ImpactLevel::High,
1008 crate::core::types::ImpactLevel::Critical => ImpactLevel::Critical,
1009 },
1010 description: b.description,
1011 optimization_suggestion: b.optimization_suggestion,
1012 })
1013 .collect(),
1014 })
1015 .collect(),
1016 performance_impact: TypePerformanceImpact {
1017 performance_score: old.performance_impact.performance_score,
1018 memory_efficiency_score: old.performance_impact.memory_efficiency_score,
1019 cpu_efficiency_score: old.performance_impact.cpu_efficiency_score,
1020 cache_efficiency_score: old.performance_impact.cache_efficiency_score,
1021 optimization_recommendations: old
1022 .performance_impact
1023 .optimization_recommendations
1024 .into_iter()
1025 .map(|r| OptimizationRecommendation {
1026 recommendation_type: match r.recommendation_type {
1027 crate::core::types::RecommendationType::MemoryLayout => {
1028 RecommendationType::MemoryLayout
1029 }
1030 crate::core::types::RecommendationType::AlgorithmChange => {
1031 RecommendationType::AlgorithmChange
1032 }
1033 crate::core::types::RecommendationType::DataStructureChange => {
1034 RecommendationType::DataStructureChange
1035 }
1036 crate::core::types::RecommendationType::CachingStrategy => {
1037 RecommendationType::CachingStrategy
1038 }
1039 crate::core::types::RecommendationType::MemoryPooling => {
1040 RecommendationType::MemoryPooling
1041 }
1042 crate::core::types::RecommendationType::LazyInitialization => {
1043 RecommendationType::LazyInitialization
1044 }
1045 crate::core::types::RecommendationType::Inlining => {
1046 RecommendationType::Inlining
1047 }
1048 crate::core::types::RecommendationType::Vectorization => {
1049 RecommendationType::Vectorization
1050 }
1051 crate::core::types::RecommendationType::Parallelization => {
1052 RecommendationType::Parallelization
1053 }
1054 },
1055 priority: match r.priority {
1056 crate::core::types::Priority::Low => Priority::Low,
1057 crate::core::types::Priority::Medium => Priority::Medium,
1058 crate::core::types::Priority::High => Priority::High,
1059 crate::core::types::Priority::Critical => Priority::Critical,
1060 },
1061 description: r.description,
1062 expected_improvement: r.expected_improvement,
1063 implementation_difficulty: match r.implementation_difficulty {
1064 crate::core::types::ImplementationDifficulty::Easy => {
1065 ImplementationDifficulty::Easy
1066 }
1067 crate::core::types::ImplementationDifficulty::Medium => {
1068 ImplementationDifficulty::Medium
1069 }
1070 crate::core::types::ImplementationDifficulty::Hard => {
1071 ImplementationDifficulty::Hard
1072 }
1073 crate::core::types::ImplementationDifficulty::VeryHard => {
1074 ImplementationDifficulty::VeryHard
1075 }
1076 },
1077 })
1078 .collect(),
1079 },
1080 }
1081 }
1082}
1083
1084#[cfg(test)]
1085mod tests {
1086 use super::*;
1087
1088 #[test]
1089 fn test_allocation_info_creation() {
1090 let info = AllocationInfo::new(0x12345678, 1024);
1091
1092 assert_eq!(info.ptr, 0x12345678);
1093 assert_eq!(info.size, 1024);
1094 assert!(info.is_active());
1095 assert!(info.borrow_info.is_none());
1096 assert!(info.clone_info.is_some());
1097 assert!(!info.ownership_history_available);
1098 }
1099
1100 #[test]
1101 fn test_allocation_info_mark_deallocated() {
1102 let mut info = AllocationInfo::new(0x1000, 512);
1103 assert!(info.is_active());
1104
1105 info.mark_deallocated();
1106 assert!(!info.is_active());
1107 assert!(info.timestamp_dealloc.is_some());
1108 }
1109
1110 #[test]
1111 fn test_allocation_info_enhance_with_type_info() {
1112 let mut info = AllocationInfo::new(0x1000, 512);
1113
1114 info.enhance_with_type_info("std::rc::Rc<String>");
1116 if let Some(clone_info) = &info.clone_info {
1117 assert_eq!(clone_info.clone_count, 2);
1118 }
1119
1120 info.enhance_with_type_info("Vec<i32>");
1122 if let Some(borrow_info) = &info.borrow_info {
1123 assert_eq!(borrow_info.immutable_borrows, 4);
1124 assert_eq!(borrow_info.mutable_borrows, 2);
1125 }
1126 }
1127
1128 #[test]
1129 fn test_borrow_info_default() {
1130 let borrow_info = BorrowInfo::default();
1131
1132 assert_eq!(borrow_info.immutable_borrows, 0);
1133 assert_eq!(borrow_info.mutable_borrows, 0);
1134 assert_eq!(borrow_info.max_concurrent_borrows, 0);
1135 assert_eq!(borrow_info.last_borrow_timestamp, None);
1136 }
1137
1138 #[test]
1139 fn test_clone_info_default() {
1140 let clone_info = CloneInfo::default();
1141
1142 assert_eq!(clone_info.clone_count, 0);
1143 assert!(!clone_info.is_clone);
1144 assert_eq!(clone_info.original_ptr, None);
1145 }
1146
1147 #[test]
1148 fn test_allocation_info_serialization() {
1149 let info = AllocationInfo::new(0x1000, 512);
1150
1151 let serialized = serde_json::to_string(&info);
1153 assert!(serialized.is_ok());
1154
1155 let json_str = serialized.expect("Failed to serialize AllocationInfo to JSON");
1157 assert!(json_str.contains("ptr"));
1158 assert!(json_str.contains("size"));
1159 }
1160}