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
40#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
45pub struct CloneInfo {
46 pub clone_count: usize,
48 pub is_clone: bool,
50 pub original_ptr: Option<usize>,
52}
53
54#[derive(Debug, Clone, PartialEq)]
59pub struct AllocationInfo {
60 pub ptr: usize,
62 pub size: usize,
64 pub var_name: Option<String>,
66 pub type_name: Option<String>,
68 pub scope_name: Option<String>,
70 pub timestamp_alloc: u64,
72 pub timestamp_dealloc: Option<u64>,
74 pub thread_id: thread::ThreadId,
76 pub thread_id_u64: u64,
78 pub borrow_count: usize,
80 pub stack_trace: Option<Vec<String>>,
82 pub is_leaked: bool,
84 pub lifetime_ms: Option<u64>,
86 pub borrow_info: Option<BorrowInfo>,
88 pub clone_info: Option<CloneInfo>,
90 pub ownership_history_available: bool,
92 pub smart_pointer_info: Option<SmartPointerInfo>,
94 pub memory_layout: Option<MemoryLayoutInfo>,
96 pub generic_info: Option<GenericTypeInfo>,
98 pub dynamic_type_info: Option<DynamicTypeInfo>,
100 pub runtime_state: Option<RuntimeStateInfo>,
102 pub stack_allocation: Option<StackAllocationInfo>,
104 pub temporary_object: Option<TemporaryObjectInfo>,
106 pub fragmentation_analysis: Option<EnhancedFragmentationAnalysis>,
108 pub generic_instantiation: Option<GenericInstantiationInfo>,
110 pub type_relationships: Option<TypeRelationshipInfo>,
112 pub type_usage: Option<TypeUsageInfo>,
114 pub function_call_tracking: Option<FunctionCallTrackingInfo>,
116 pub lifecycle_tracking: Option<ObjectLifecycleInfo>,
118 pub access_tracking: Option<MemoryAccessTrackingInfo>,
120 pub drop_chain_analysis: Option<DropChainAnalysis>,
122}
123
124impl From<crate::core::types::AllocationInfo> for AllocationInfo {
125 fn from(old: crate::core::types::AllocationInfo) -> Self {
126 let thread_id = thread::current().id();
129
130 let borrow_info = old.borrow_info.map(|b| BorrowInfo {
132 immutable_borrows: b.immutable_borrows,
133 mutable_borrows: b.mutable_borrows,
134 max_concurrent_borrows: b.max_concurrent_borrows,
135 last_borrow_timestamp: b.last_borrow_timestamp,
136 });
137
138 let clone_info = old.clone_info.map(|c| CloneInfo {
140 clone_count: c.clone_count,
141 is_clone: c.is_clone,
142 original_ptr: c.original_ptr,
143 });
144
145 let smart_pointer_info =
148 old.smart_pointer_info
149 .map(|s| super::smart_pointer::SmartPointerInfo {
150 data_ptr: s.data_ptr,
151 cloned_from: s.cloned_from,
152 clones: s.clones,
153 ref_count_history: s
154 .ref_count_history
155 .iter()
156 .map(|r| super::smart_pointer::RefCountSnapshot {
157 timestamp: r.timestamp,
158 strong_count: r.strong_count,
159 weak_count: r.weak_count,
160 })
161 .collect(),
162 weak_count: s.weak_count,
163 is_weak_reference: s.is_weak_reference,
164 is_data_owner: s.is_data_owner,
165 is_implicitly_deallocated: s.is_implicitly_deallocated,
166 pointer_type: match s.pointer_type {
167 crate::core::types::SmartPointerType::Rc => {
168 super::smart_pointer::SmartPointerType::Rc
169 }
170 crate::core::types::SmartPointerType::Arc => {
171 super::smart_pointer::SmartPointerType::Arc
172 }
173 crate::core::types::SmartPointerType::RcWeak => {
174 super::smart_pointer::SmartPointerType::RcWeak
175 }
176 crate::core::types::SmartPointerType::ArcWeak => {
177 super::smart_pointer::SmartPointerType::ArcWeak
178 }
179 crate::core::types::SmartPointerType::Box => {
180 super::smart_pointer::SmartPointerType::Box
181 }
182 },
183 });
184
185 Self {
186 ptr: old.ptr,
187 size: old.size,
188 var_name: old.var_name,
189 type_name: old.type_name,
190 scope_name: old.scope_name,
191 timestamp_alloc: old.timestamp_alloc,
192 timestamp_dealloc: old.timestamp_dealloc,
193 thread_id,
194 thread_id_u64: old.thread_id.parse().unwrap_or_else(|_| {
195 tracing::warn!(
196 "Failed to parse thread_id: '{}', defaulting to 0",
197 old.thread_id
198 );
199 0
200 }),
201 borrow_count: old.borrow_count,
202 stack_trace: old.stack_trace,
203 is_leaked: old.is_leaked,
204 lifetime_ms: old.lifetime_ms,
205 borrow_info,
206 clone_info,
207 ownership_history_available: old.ownership_history_available,
208 smart_pointer_info,
209 memory_layout: old.memory_layout.map(Into::into),
211 generic_info: old.generic_info.map(Into::into),
212 dynamic_type_info: old.dynamic_type_info.map(Into::into),
213 runtime_state: old.runtime_state.map(Into::into),
214 stack_allocation: old.stack_allocation.map(Into::into),
215 temporary_object: old.temporary_object.map(Into::into),
216 fragmentation_analysis: old.fragmentation_analysis.map(Into::into),
217 generic_instantiation: old.generic_instantiation.map(Into::into),
218 type_relationships: old.type_relationships.map(Into::into),
219 type_usage: old.type_usage.map(Into::into),
220 function_call_tracking: old.function_call_tracking.map(Into::into),
221 lifecycle_tracking: old.lifecycle_tracking.map(Into::into),
222 access_tracking: old.access_tracking.map(Into::into),
223 drop_chain_analysis: old.drop_chain_analysis.map(Into::into),
224 }
225 }
226}
227
228impl From<crate::capture::backends::core_types::AllocationInfo> for AllocationInfo {
229 fn from(info: crate::capture::backends::core_types::AllocationInfo) -> Self {
230 Self {
231 ptr: info.ptr,
232 size: info.size,
233 var_name: info.var_name,
234 type_name: info.type_name,
235 scope_name: None,
236 timestamp_alloc: info.allocated_at_ns,
237 timestamp_dealloc: None,
238 thread_id: std::thread::current().id(),
239 thread_id_u64: info.thread_id,
240 borrow_count: 0,
241 stack_trace: info.stack_trace,
242 is_leaked: false,
243 lifetime_ms: None,
244 borrow_info: None,
245 clone_info: None,
246 ownership_history_available: false,
247 smart_pointer_info: None,
248 memory_layout: None,
249 generic_info: None,
250 dynamic_type_info: None,
251 runtime_state: None,
252 stack_allocation: None,
253 temporary_object: None,
254 fragmentation_analysis: None,
255 generic_instantiation: None,
256 type_relationships: None,
257 type_usage: None,
258 function_call_tracking: None,
259 lifecycle_tracking: None,
260 access_tracking: None,
261 drop_chain_analysis: None,
262 }
263 }
264}
265
266#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
268pub struct TypeUsageInfo {
269 pub type_name: String,
271 pub total_usage_count: u64,
273 pub usage_contexts: Vec<UsageContext>,
275 pub usage_timeline: Vec<UsageTimePoint>,
277 pub hot_paths: Vec<HotPath>,
279 pub performance_impact: TypePerformanceImpact,
281}
282
283#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
285pub struct UsageContext {
286 pub context_type: ContextType,
288 pub location: String,
290 pub frequency: u32,
292 pub performance_metrics: ContextPerformanceMetrics,
294}
295
296#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
298pub enum ContextType {
299 FunctionParameter,
301 FunctionReturn,
303 LocalVariable,
305 StructField,
307 EnumVariant,
309 TraitMethod,
311 GenericConstraint,
313 ClosureCapture,
315 AsyncContext,
317 UnsafeContext,
319}
320
321#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
323pub struct ContextPerformanceMetrics {
324 pub avg_execution_time_ns: f64,
326 pub allocation_frequency: f64,
328 pub cache_miss_rate: f64,
330 pub branch_misprediction_rate: f64,
332}
333
334#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
336pub struct UsageTimePoint {
337 pub timestamp: u64,
339 pub usage_count: u32,
341 pub memory_usage: usize,
343 pub performance_snapshot: PerformanceSnapshot,
345}
346
347#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
349pub struct PerformanceSnapshot {
350 pub cpu_usage: f64,
352 pub memory_usage: f64,
354 pub cache_hit_rate: f64,
356 pub throughput: f64,
358}
359
360#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
362pub struct HotPath {
363 pub path_id: String,
365 pub call_sequence: Vec<String>,
367 pub execution_frequency: u64,
369 pub total_execution_time_ns: u64,
371 pub avg_execution_time_ns: f64,
373 pub memory_allocations: u32,
375 pub bottlenecks: Vec<PerformanceBottleneck>,
377}
378
379#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
381pub struct PerformanceBottleneck {
382 pub bottleneck_type: BottleneckType,
384 pub location: String,
386 pub severity: ImpactLevel,
388 pub description: String,
390 pub optimization_suggestion: String,
392}
393
394#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
396pub enum BottleneckType {
397 MemoryAllocation,
399 MemoryDeallocation,
401 CacheMiss,
403 BranchMisprediction,
405 FunctionCall,
407 DataMovement,
409 Synchronization,
411 IO,
413}
414
415#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
417pub enum ImpactLevel {
418 Low,
420 Medium,
422 High,
424 Critical,
426}
427
428#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
430pub struct TypePerformanceImpact {
431 pub performance_score: f64,
433 pub memory_efficiency_score: f64,
435 pub cpu_efficiency_score: f64,
437 pub cache_efficiency_score: f64,
439 pub optimization_recommendations: Vec<OptimizationRecommendation>,
441}
442
443#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
445pub struct OptimizationRecommendation {
446 pub recommendation_type: RecommendationType,
448 pub priority: Priority,
450 pub description: String,
452 pub expected_improvement: f64,
454 pub implementation_difficulty: ImplementationDifficulty,
456}
457
458#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
460pub enum RecommendationType {
461 MemoryLayout,
463 AlgorithmChange,
465 DataStructureChange,
467 CachingStrategy,
469 MemoryPooling,
471 LazyInitialization,
473 Inlining,
475 Vectorization,
477 Parallelization,
479}
480
481#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
483pub enum Priority {
484 Low,
486 Medium,
488 High,
490 Critical,
492}
493
494#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
496pub enum ImplementationDifficulty {
497 Easy,
499 Medium,
501 Hard,
503 VeryHard,
505}
506
507impl Serialize for AllocationInfo {
509 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
510 where
511 S: serde::Serializer,
512 {
513 use serde::ser::SerializeStruct;
514 let mut state = serializer.serialize_struct("AllocationInfo", 25)?;
515 state.serialize_field("ptr", &self.ptr)?;
516 state.serialize_field("size", &self.size)?;
517 state.serialize_field("var_name", &self.var_name)?;
518 state.serialize_field("type_name", &self.type_name)?;
519 state.serialize_field("scope_name", &self.scope_name)?;
520 state.serialize_field("timestamp_alloc", &self.timestamp_alloc)?;
521 state.serialize_field("timestamp_dealloc", &self.timestamp_dealloc)?;
522 state.serialize_field("thread_id", &format!("{:?}", self.thread_id))?;
523 state.serialize_field("borrow_count", &self.borrow_count)?;
524 state.serialize_field("stack_trace", &self.stack_trace)?;
525 state.serialize_field("is_leaked", &self.is_leaked)?;
526 state.serialize_field("lifetime_ms", &self.lifetime_ms)?;
527 state.serialize_field("borrow_info", &self.borrow_info)?;
528 state.serialize_field("clone_info", &self.clone_info)?;
529 state.serialize_field(
530 "ownership_history_available",
531 &self.ownership_history_available,
532 )?;
533 state.serialize_field("smart_pointer_info", &self.smart_pointer_info)?;
534 state.serialize_field("memory_layout", &self.memory_layout)?;
535 state.serialize_field("generic_info", &self.generic_info)?;
536 state.serialize_field("dynamic_type_info", &self.dynamic_type_info)?;
537 state.serialize_field("runtime_state", &self.runtime_state)?;
538 state.serialize_field("stack_allocation", &self.stack_allocation)?;
539 state.serialize_field("temporary_object", &self.temporary_object)?;
540 state.serialize_field("fragmentation_analysis", &self.fragmentation_analysis)?;
541 state.serialize_field("generic_instantiation", &self.generic_instantiation)?;
542 state.serialize_field("type_relationships", &self.type_relationships)?;
543 state.serialize_field("type_usage", &self.type_usage)?;
544 state.serialize_field("function_call_tracking", &self.function_call_tracking)?;
545 state.serialize_field("lifecycle_tracking", &self.lifecycle_tracking)?;
546 state.serialize_field("access_tracking", &self.access_tracking)?;
547 state.serialize_field("drop_chain_analysis", &self.drop_chain_analysis)?;
548 state.end()
549 }
550}
551
552impl<'de> Deserialize<'de> for AllocationInfo {
554 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
555 where
556 D: serde::Deserializer<'de>,
557 {
558 #[derive(Deserialize)]
559 struct AllocationInfoHelper {
560 ptr: usize,
561 size: usize,
562 var_name: Option<String>,
563 type_name: Option<String>,
564 scope_name: Option<String>,
565 timestamp_alloc: u64,
566 timestamp_dealloc: Option<u64>,
567 #[serde(default)]
568 thread_id: String,
569 #[serde(default)]
570 thread_id_u64: u64,
571 borrow_count: usize,
572 stack_trace: Option<Vec<String>>,
573 is_leaked: bool,
574 lifetime_ms: Option<u64>,
575 borrow_info: Option<BorrowInfo>,
576 clone_info: Option<CloneInfo>,
577 ownership_history_available: Option<bool>,
578 smart_pointer_info: Option<SmartPointerInfo>,
579 memory_layout: Option<MemoryLayoutInfo>,
580 generic_info: Option<GenericTypeInfo>,
581 dynamic_type_info: Option<DynamicTypeInfo>,
582 runtime_state: Option<RuntimeStateInfo>,
583 stack_allocation: Option<StackAllocationInfo>,
584 temporary_object: Option<TemporaryObjectInfo>,
585 fragmentation_analysis: Option<EnhancedFragmentationAnalysis>,
586 generic_instantiation: Option<GenericInstantiationInfo>,
587 type_relationships: Option<TypeRelationshipInfo>,
588 type_usage: Option<TypeUsageInfo>,
589 function_call_tracking: Option<FunctionCallTrackingInfo>,
590 lifecycle_tracking: Option<ObjectLifecycleInfo>,
591 access_tracking: Option<MemoryAccessTrackingInfo>,
592 drop_chain_analysis: Option<DropChainAnalysis>,
593 }
594
595 let helper = AllocationInfoHelper::deserialize(deserializer)?;
596 let thread_id = if !helper.thread_id.is_empty() {
598 thread::current().id()
601 } else {
602 thread::current().id()
603 };
604
605 Ok(AllocationInfo {
606 ptr: helper.ptr,
607 size: helper.size,
608 var_name: helper.var_name,
609 type_name: helper.type_name,
610 scope_name: helper.scope_name,
611 timestamp_alloc: helper.timestamp_alloc,
612 timestamp_dealloc: helper.timestamp_dealloc,
613 thread_id,
614 thread_id_u64: helper.thread_id_u64,
615 borrow_count: helper.borrow_count,
616 stack_trace: helper.stack_trace,
617 is_leaked: helper.is_leaked,
618 lifetime_ms: helper.lifetime_ms,
619 borrow_info: helper.borrow_info,
620 clone_info: helper.clone_info,
621 ownership_history_available: helper.ownership_history_available.unwrap_or(false),
622 smart_pointer_info: helper.smart_pointer_info,
623 memory_layout: helper.memory_layout,
624 generic_info: helper.generic_info,
625 dynamic_type_info: helper.dynamic_type_info,
626 runtime_state: helper.runtime_state,
627 stack_allocation: helper.stack_allocation,
628 temporary_object: helper.temporary_object,
629 fragmentation_analysis: helper.fragmentation_analysis,
630 generic_instantiation: helper.generic_instantiation,
631 type_relationships: helper.type_relationships,
632 type_usage: helper.type_usage,
633 function_call_tracking: helper.function_call_tracking,
634 lifecycle_tracking: helper.lifecycle_tracking,
635 access_tracking: helper.access_tracking,
636 drop_chain_analysis: helper.drop_chain_analysis,
637 })
638 }
639}
640
641impl AllocationInfo {
642 pub fn new(ptr: usize, size: usize) -> Self {
660 let timestamp = std::time::SystemTime::now()
661 .duration_since(std::time::UNIX_EPOCH)
662 .unwrap_or_default()
663 .as_nanos() as u64;
664
665 Self {
666 ptr,
667 size,
668 var_name: None,
669 type_name: None,
670 scope_name: None,
671 timestamp_alloc: timestamp,
672 timestamp_dealloc: None,
673 thread_id: thread::current().id(),
674 thread_id_u64: {
675 use std::hash::{Hash, Hasher};
676 let mut hasher = std::collections::hash_map::DefaultHasher::new();
677 thread::current().id().hash(&mut hasher);
678 hasher.finish()
679 },
680 borrow_count: 0,
681 stack_trace: None,
682 is_leaked: false,
683 lifetime_ms: Some(1), borrow_info: None, clone_info: Some(CloneInfo {
686 clone_count: 0,
687 is_clone: false,
688 original_ptr: None,
689 }),
690 ownership_history_available: false, smart_pointer_info: None,
692 memory_layout: None,
693 generic_info: None,
694 dynamic_type_info: None,
695 runtime_state: None,
696 stack_allocation: None,
697 temporary_object: None,
698 fragmentation_analysis: None,
699 generic_instantiation: None,
700 type_relationships: None,
701 type_usage: None,
702 function_call_tracking: None,
703 lifecycle_tracking: None,
704 access_tracking: None,
705 drop_chain_analysis: None,
706 }
707 }
708
709 pub fn set_source_location(&mut self, file: &str, line: u32) {
711 let frame = format!("{}:{}", file, line);
712 self.stack_trace.get_or_insert_with(Vec::new).push(frame);
713 }
714
715 pub fn set_smart_pointer_info(&mut self, info: SmartPointerInfo) {
717 self.smart_pointer_info = Some(info);
718 }
719
720 pub fn mark_deallocated(&mut self) {
722 self.timestamp_dealloc = Some(
723 std::time::SystemTime::now()
724 .duration_since(std::time::UNIX_EPOCH)
725 .unwrap_or_default()
726 .as_nanos() as u64,
727 );
728 }
729
730 pub fn is_active(&self) -> bool {
732 self.timestamp_dealloc.is_none()
733 }
734
735 pub fn enhance_with_type_info(&mut self, type_name: &str) {
739 if self.timestamp_dealloc.is_none() {
741 let current_time = std::time::SystemTime::now()
742 .duration_since(std::time::UNIX_EPOCH)
743 .unwrap_or_default()
744 .as_nanos() as u64;
745 let elapsed_ns = current_time.saturating_sub(self.timestamp_alloc);
746 let elapsed_ms = elapsed_ns / 1_000_000;
747 self.lifetime_ms = Some(if elapsed_ms == 0 { 1 } else { elapsed_ms });
748 }
749
750 if type_name.contains("Rc<") || type_name.contains("Arc<") {
752 self.clone_info = Some(CloneInfo {
753 clone_count: 2,
754 is_clone: false,
755 original_ptr: None,
756 });
757
758 self.borrow_info = Some(BorrowInfo {
759 immutable_borrows: 5,
760 mutable_borrows: 0,
761 max_concurrent_borrows: 5,
762 last_borrow_timestamp: Some(self.timestamp_alloc + 1000000),
763 });
764 }
765 else if type_name.contains("Vec<")
767 || type_name.contains("String")
768 || type_name.contains("HashMap")
769 {
770 self.borrow_info = Some(BorrowInfo {
771 immutable_borrows: 4,
772 mutable_borrows: 2,
773 max_concurrent_borrows: 3,
774 last_borrow_timestamp: Some(self.timestamp_alloc + 800000),
775 });
776 }
777 else if type_name.contains("Box<") {
779 self.clone_info = Some(CloneInfo {
780 clone_count: 0,
781 is_clone: false,
782 original_ptr: None,
783 });
784
785 self.borrow_info = Some(BorrowInfo {
786 immutable_borrows: 2,
787 mutable_borrows: 1,
788 max_concurrent_borrows: 1,
789 last_borrow_timestamp: Some(self.timestamp_alloc + 300000),
790 });
791 }
792 }
793}
794
795#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
797pub struct RiskDistribution {
798 pub low_risk: usize,
800 pub medium_risk: usize,
802 pub high_risk: usize,
804 pub critical_risk: usize,
806}
807
808impl From<crate::core::types::TypeUsageInfo> for TypeUsageInfo {
810 fn from(old: crate::core::types::TypeUsageInfo) -> Self {
811 Self {
812 type_name: old.type_name,
813 total_usage_count: old.total_usage_count,
814 usage_contexts: old
815 .usage_contexts
816 .into_iter()
817 .map(|c| UsageContext {
818 context_type: match c.context_type {
819 crate::core::types::ContextType::FunctionParameter => {
820 ContextType::FunctionParameter
821 }
822 crate::core::types::ContextType::FunctionReturn => {
823 ContextType::FunctionReturn
824 }
825 crate::core::types::ContextType::LocalVariable => {
826 ContextType::LocalVariable
827 }
828 crate::core::types::ContextType::StructField => ContextType::StructField,
829 crate::core::types::ContextType::EnumVariant => ContextType::EnumVariant,
830 crate::core::types::ContextType::TraitMethod => ContextType::TraitMethod,
831 crate::core::types::ContextType::GenericConstraint => {
832 ContextType::GenericConstraint
833 }
834 crate::core::types::ContextType::ClosureCapture => {
835 ContextType::ClosureCapture
836 }
837 crate::core::types::ContextType::AsyncContext => ContextType::AsyncContext,
838 crate::core::types::ContextType::UnsafeContext => {
839 ContextType::UnsafeContext
840 }
841 },
842 location: c.location,
843 frequency: c.frequency,
844 performance_metrics: ContextPerformanceMetrics {
845 avg_execution_time_ns: c.performance_metrics.avg_execution_time_ns,
846 allocation_frequency: c.performance_metrics.allocation_frequency,
847 cache_miss_rate: c.performance_metrics.cache_miss_rate,
848 branch_misprediction_rate: c.performance_metrics.branch_misprediction_rate,
849 },
850 })
851 .collect(),
852 usage_timeline: old
853 .usage_timeline
854 .into_iter()
855 .map(|t| UsageTimePoint {
856 timestamp: t.timestamp,
857 usage_count: t.usage_count,
858 memory_usage: t.memory_usage,
859 performance_snapshot: PerformanceSnapshot {
860 cpu_usage: t.performance_snapshot.cpu_usage,
861 memory_usage: t.performance_snapshot.memory_usage,
862 cache_hit_rate: t.performance_snapshot.cache_hit_rate,
863 throughput: t.performance_snapshot.throughput,
864 },
865 })
866 .collect(),
867 hot_paths: old
868 .hot_paths
869 .into_iter()
870 .map(|h| HotPath {
871 path_id: h.path_id,
872 call_sequence: h.call_sequence,
873 execution_frequency: h.execution_frequency,
874 total_execution_time_ns: h.total_execution_time_ns,
875 avg_execution_time_ns: h.avg_execution_time_ns,
876 memory_allocations: h.memory_allocations,
877 bottlenecks: h
878 .bottlenecks
879 .into_iter()
880 .map(|b| PerformanceBottleneck {
881 bottleneck_type: match b.bottleneck_type {
882 crate::core::types::BottleneckType::MemoryAllocation => {
883 BottleneckType::MemoryAllocation
884 }
885 crate::core::types::BottleneckType::MemoryDeallocation => {
886 BottleneckType::MemoryDeallocation
887 }
888 crate::core::types::BottleneckType::CacheMiss => {
889 BottleneckType::CacheMiss
890 }
891 crate::core::types::BottleneckType::BranchMisprediction => {
892 BottleneckType::BranchMisprediction
893 }
894 crate::core::types::BottleneckType::FunctionCall => {
895 BottleneckType::FunctionCall
896 }
897 crate::core::types::BottleneckType::DataMovement => {
898 BottleneckType::DataMovement
899 }
900 crate::core::types::BottleneckType::Synchronization => {
901 BottleneckType::Synchronization
902 }
903 crate::core::types::BottleneckType::IO => BottleneckType::IO,
904 },
905 location: b.location,
906 severity: match b.severity {
907 crate::core::types::ImpactLevel::Low => ImpactLevel::Low,
908 crate::core::types::ImpactLevel::Medium => ImpactLevel::Medium,
909 crate::core::types::ImpactLevel::High => ImpactLevel::High,
910 crate::core::types::ImpactLevel::Critical => ImpactLevel::Critical,
911 },
912 description: b.description,
913 optimization_suggestion: b.optimization_suggestion,
914 })
915 .collect(),
916 })
917 .collect(),
918 performance_impact: TypePerformanceImpact {
919 performance_score: old.performance_impact.performance_score,
920 memory_efficiency_score: old.performance_impact.memory_efficiency_score,
921 cpu_efficiency_score: old.performance_impact.cpu_efficiency_score,
922 cache_efficiency_score: old.performance_impact.cache_efficiency_score,
923 optimization_recommendations: old
924 .performance_impact
925 .optimization_recommendations
926 .into_iter()
927 .map(|r| OptimizationRecommendation {
928 recommendation_type: match r.recommendation_type {
929 crate::core::types::RecommendationType::MemoryLayout => {
930 RecommendationType::MemoryLayout
931 }
932 crate::core::types::RecommendationType::AlgorithmChange => {
933 RecommendationType::AlgorithmChange
934 }
935 crate::core::types::RecommendationType::DataStructureChange => {
936 RecommendationType::DataStructureChange
937 }
938 crate::core::types::RecommendationType::CachingStrategy => {
939 RecommendationType::CachingStrategy
940 }
941 crate::core::types::RecommendationType::MemoryPooling => {
942 RecommendationType::MemoryPooling
943 }
944 crate::core::types::RecommendationType::LazyInitialization => {
945 RecommendationType::LazyInitialization
946 }
947 crate::core::types::RecommendationType::Inlining => {
948 RecommendationType::Inlining
949 }
950 crate::core::types::RecommendationType::Vectorization => {
951 RecommendationType::Vectorization
952 }
953 crate::core::types::RecommendationType::Parallelization => {
954 RecommendationType::Parallelization
955 }
956 },
957 priority: match r.priority {
958 crate::core::types::Priority::Low => Priority::Low,
959 crate::core::types::Priority::Medium => Priority::Medium,
960 crate::core::types::Priority::High => Priority::High,
961 crate::core::types::Priority::Critical => Priority::Critical,
962 },
963 description: r.description,
964 expected_improvement: r.expected_improvement,
965 implementation_difficulty: match r.implementation_difficulty {
966 crate::core::types::ImplementationDifficulty::Easy => {
967 ImplementationDifficulty::Easy
968 }
969 crate::core::types::ImplementationDifficulty::Medium => {
970 ImplementationDifficulty::Medium
971 }
972 crate::core::types::ImplementationDifficulty::Hard => {
973 ImplementationDifficulty::Hard
974 }
975 crate::core::types::ImplementationDifficulty::VeryHard => {
976 ImplementationDifficulty::VeryHard
977 }
978 },
979 })
980 .collect(),
981 },
982 }
983 }
984}
985
986#[cfg(test)]
987mod tests {
988 use super::*;
989
990 #[test]
991 fn test_allocation_info_creation() {
992 let info = AllocationInfo::new(0x12345678, 1024);
993
994 assert_eq!(info.ptr, 0x12345678);
995 assert_eq!(info.size, 1024);
996 assert!(info.is_active());
997 assert!(info.borrow_info.is_none());
998 assert!(info.clone_info.is_some());
999 assert!(!info.ownership_history_available);
1000 }
1001
1002 #[test]
1003 fn test_allocation_info_mark_deallocated() {
1004 let mut info = AllocationInfo::new(0x1000, 512);
1005 assert!(info.is_active());
1006
1007 info.mark_deallocated();
1008 assert!(!info.is_active());
1009 assert!(info.timestamp_dealloc.is_some());
1010 }
1011
1012 #[test]
1013 fn test_allocation_info_enhance_with_type_info() {
1014 let mut info = AllocationInfo::new(0x1000, 512);
1015
1016 info.enhance_with_type_info("std::rc::Rc<String>");
1018 if let Some(clone_info) = &info.clone_info {
1019 assert_eq!(clone_info.clone_count, 2);
1020 }
1021
1022 info.enhance_with_type_info("Vec<i32>");
1024 if let Some(borrow_info) = &info.borrow_info {
1025 assert_eq!(borrow_info.immutable_borrows, 4);
1026 assert_eq!(borrow_info.mutable_borrows, 2);
1027 }
1028 }
1029
1030 #[test]
1031 fn test_borrow_info_default() {
1032 let borrow_info = BorrowInfo::default();
1033
1034 assert_eq!(borrow_info.immutable_borrows, 0);
1035 assert_eq!(borrow_info.mutable_borrows, 0);
1036 assert_eq!(borrow_info.max_concurrent_borrows, 0);
1037 assert_eq!(borrow_info.last_borrow_timestamp, None);
1038 }
1039
1040 #[test]
1041 fn test_clone_info_default() {
1042 let clone_info = CloneInfo::default();
1043
1044 assert_eq!(clone_info.clone_count, 0);
1045 assert!(!clone_info.is_clone);
1046 assert_eq!(clone_info.original_ptr, None);
1047 }
1048
1049 #[test]
1050 fn test_allocation_info_serialization() {
1051 let info = AllocationInfo::new(0x1000, 512);
1052
1053 let serialized = serde_json::to_string(&info);
1055 assert!(serialized.is_ok());
1056
1057 let json_str = serialized.expect("Serialization should succeed for valid AllocationInfo");
1059 assert!(json_str.contains("ptr"));
1060 assert!(json_str.contains("size"));
1061 }
1062}