Skip to main content

memscope_rs/capture/types/
allocation.rs

1//! Allocation types for memory tracking.
2//!
3//! This module contains types related to memory allocation tracking,
4//! including allocation information, borrow tracking, and clone tracking.
5
6use serde::{Deserialize, Serialize};
7use std::thread;
8
9// Import related types from other modules
10use 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/// Enhanced borrowing information for allocations.
25///
26/// Tracks borrow patterns including immutable and mutable borrows,
27/// concurrent borrow counts, and timestamp information.
28#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
29pub struct BorrowInfo {
30    /// Total number of immutable borrows during lifetime.
31    pub immutable_borrows: usize,
32    /// Total number of mutable borrows during lifetime.
33    pub mutable_borrows: usize,
34    /// Peak number of simultaneous borrows observed.
35    pub max_concurrent_borrows: usize,
36    /// Timestamp of the last borrow event.
37    pub last_borrow_timestamp: Option<u64>,
38}
39
40/// Enhanced cloning information for allocations.
41///
42/// Tracks clone operations including clone counts, original source
43/// tracking, and clone relationships.
44#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
45pub struct CloneInfo {
46    /// Number of times this object was cloned.
47    pub clone_count: usize,
48    /// Whether this allocation itself is a result of a clone.
49    pub is_clone: bool,
50    /// If is_clone is true, points to the original object's pointer.
51    pub original_ptr: Option<usize>,
52}
53
54/// Information about a memory allocation.
55///
56/// Comprehensive tracking information for a single memory allocation,
57/// including size, type, scope, lifecycle, and various analysis metadata.
58#[derive(Debug, Clone, PartialEq)]
59pub struct AllocationInfo {
60    /// Memory address of the allocation.
61    pub ptr: usize,
62    /// Size of the allocation in bytes.
63    pub size: usize,
64    /// Optional variable name associated with this allocation.
65    pub var_name: Option<String>,
66    /// Optional type name of the allocated data.
67    pub type_name: Option<String>,
68    /// Optional scope name where the allocation occurred.
69    pub scope_name: Option<String>,
70    /// Timestamp when the allocation was made.
71    pub timestamp_alloc: u64,
72    /// Optional timestamp when the allocation was deallocated.
73    pub timestamp_dealloc: Option<u64>,
74    /// Thread ID where the allocation occurred.
75    pub thread_id: thread::ThreadId,
76    /// Thread ID as u64 (original value from tracking).
77    pub thread_id_u64: u64,
78    /// Number of active borrows for this allocation.
79    pub borrow_count: usize,
80    /// Optional stack trace at the time of allocation.
81    pub stack_trace: Option<Vec<String>>,
82    /// Whether this allocation is considered leaked.
83    pub is_leaked: bool,
84    /// Precise lifetime in milliseconds (calculated from creation to destruction).
85    pub lifetime_ms: Option<u64>,
86    /// Enhanced borrowing information.
87    pub borrow_info: Option<BorrowInfo>,
88    /// Enhanced cloning information.
89    pub clone_info: Option<CloneInfo>,
90    /// Flag indicating if detailed ownership history is available in lifetime.json.
91    pub ownership_history_available: bool,
92    /// Smart pointer specific information.
93    pub smart_pointer_info: Option<SmartPointerInfo>,
94    /// Detailed memory layout information.
95    pub memory_layout: Option<MemoryLayoutInfo>,
96    /// Generic type information.
97    pub generic_info: Option<GenericTypeInfo>,
98    /// Dynamic type information (trait objects).
99    pub dynamic_type_info: Option<DynamicTypeInfo>,
100    /// Runtime state information.
101    pub runtime_state: Option<RuntimeStateInfo>,
102    /// Stack allocation information (if allocated on stack).
103    pub stack_allocation: Option<StackAllocationInfo>,
104    /// Temporary object information (if this is a temporary).
105    pub temporary_object: Option<TemporaryObjectInfo>,
106    /// Memory fragmentation analysis.
107    pub fragmentation_analysis: Option<EnhancedFragmentationAnalysis>,
108    /// Enhanced generic instantiation tracking.
109    pub generic_instantiation: Option<GenericInstantiationInfo>,
110    /// Type relationship information.
111    pub type_relationships: Option<TypeRelationshipInfo>,
112    /// Type usage information.
113    pub type_usage: Option<TypeUsageInfo>,
114    /// Function call tracking (if allocation is function-related).
115    pub function_call_tracking: Option<FunctionCallTrackingInfo>,
116    /// Object lifecycle tracking.
117    pub lifecycle_tracking: Option<ObjectLifecycleInfo>,
118    /// Memory access pattern tracking.
119    pub access_tracking: Option<MemoryAccessTrackingInfo>,
120    /// Drop chain analysis (when object is dropped).
121    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        // For thread_id, we use a default value since ThreadId cannot be reliably reconstructed from String
127        // In a production system, this would require proper thread ID tracking
128        let thread_id = thread::current().id();
129
130        // Convert borrow_info
131        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        // Convert clone_info
139        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        // For complex nested types, we set them to None to avoid complex conversions
146        // In a production system, these would need proper conversion implementations
147        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            // Complex nested types - use Into::into for complete conversion
210            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/// Type usage information for tracking how types are used across the codebase.
267#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
268pub struct TypeUsageInfo {
269    /// Type name.
270    pub type_name: String,
271    /// Total usage count.
272    pub total_usage_count: u64,
273    /// Usage contexts.
274    pub usage_contexts: Vec<UsageContext>,
275    /// Usage patterns over time.
276    pub usage_timeline: Vec<UsageTimePoint>,
277    /// Hot paths where type is used.
278    pub hot_paths: Vec<HotPath>,
279    /// Performance impact of usage.
280    pub performance_impact: TypePerformanceImpact,
281}
282
283/// Usage context information.
284#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
285pub struct UsageContext {
286    /// Context type.
287    pub context_type: ContextType,
288    /// Function or module name.
289    pub location: String,
290    /// Usage frequency in this context.
291    pub frequency: u32,
292    /// Performance characteristics in this context.
293    pub performance_metrics: ContextPerformanceMetrics,
294}
295
296/// Context types where types are used.
297#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
298pub enum ContextType {
299    /// Function parameter context.
300    FunctionParameter,
301    /// Function return context.
302    FunctionReturn,
303    /// Local variable context.
304    LocalVariable,
305    /// Struct field context.
306    StructField,
307    /// Enum variant context.
308    EnumVariant,
309    /// Trait method context.
310    TraitMethod,
311    /// Generic constraint context.
312    GenericConstraint,
313    /// Closure capture context.
314    ClosureCapture,
315    /// Async context.
316    AsyncContext,
317    /// Unsafe context.
318    UnsafeContext,
319}
320
321/// Performance metrics within specific contexts.
322#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
323pub struct ContextPerformanceMetrics {
324    /// Average execution time in this context.
325    pub avg_execution_time_ns: f64,
326    /// Memory allocation frequency.
327    pub allocation_frequency: f64,
328    /// Cache miss rate in this context.
329    pub cache_miss_rate: f64,
330    /// Branch misprediction rate.
331    pub branch_misprediction_rate: f64,
332}
333
334/// Usage time point for timeline analysis.
335#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
336pub struct UsageTimePoint {
337    /// Timestamp.
338    pub timestamp: u64,
339    /// Usage count at this time.
340    pub usage_count: u32,
341    /// Memory usage at this time.
342    pub memory_usage: usize,
343    /// Performance metrics at this time.
344    pub performance_snapshot: PerformanceSnapshot,
345}
346
347/// Performance snapshot at a specific time.
348#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
349pub struct PerformanceSnapshot {
350    /// CPU usage percentage.
351    pub cpu_usage: f64,
352    /// Memory usage percentage.
353    pub memory_usage: f64,
354    /// Cache hit rate.
355    pub cache_hit_rate: f64,
356    /// Throughput (operations per second).
357    pub throughput: f64,
358}
359
360/// Hot path information.
361#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
362pub struct HotPath {
363    /// Path identifier.
364    pub path_id: String,
365    /// Function call sequence.
366    pub call_sequence: Vec<String>,
367    /// Execution frequency.
368    pub execution_frequency: u64,
369    /// Total execution time.
370    pub total_execution_time_ns: u64,
371    /// Average execution time.
372    pub avg_execution_time_ns: f64,
373    /// Memory allocations in this path.
374    pub memory_allocations: u32,
375    /// Performance bottlenecks.
376    pub bottlenecks: Vec<PerformanceBottleneck>,
377}
378
379/// Performance bottleneck information.
380#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
381pub struct PerformanceBottleneck {
382    /// Bottleneck type.
383    pub bottleneck_type: BottleneckType,
384    /// Location in code.
385    pub location: String,
386    /// Impact severity.
387    pub severity: ImpactLevel,
388    /// Description.
389    pub description: String,
390    /// Suggested optimization.
391    pub optimization_suggestion: String,
392}
393
394/// Types of performance bottlenecks.
395#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
396pub enum BottleneckType {
397    /// Memory allocation bottleneck.
398    MemoryAllocation,
399    /// Memory deallocation bottleneck.
400    MemoryDeallocation,
401    /// Cache miss bottleneck.
402    CacheMiss,
403    /// Branch misprediction bottleneck.
404    BranchMisprediction,
405    /// Function call bottleneck.
406    FunctionCall,
407    /// Data movement bottleneck.
408    DataMovement,
409    /// Synchronization bottleneck.
410    Synchronization,
411    /// I/O bottleneck.
412    IO,
413}
414
415/// Impact level enumeration.
416#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
417pub enum ImpactLevel {
418    /// Low impact level.
419    Low,
420    /// Medium impact level.
421    Medium,
422    /// High impact level.
423    High,
424    /// Critical impact level.
425    Critical,
426}
427
428/// Type performance impact assessment.
429#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
430pub struct TypePerformanceImpact {
431    /// Overall performance score (0-100).
432    pub performance_score: f64,
433    /// Memory efficiency score (0-100).
434    pub memory_efficiency_score: f64,
435    /// CPU efficiency score (0-100).
436    pub cpu_efficiency_score: f64,
437    /// Cache efficiency score (0-100).
438    pub cache_efficiency_score: f64,
439    /// Optimization recommendations.
440    pub optimization_recommendations: Vec<OptimizationRecommendation>,
441}
442
443/// Optimization recommendation.
444#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
445pub struct OptimizationRecommendation {
446    /// Recommendation type.
447    pub recommendation_type: RecommendationType,
448    /// Priority level.
449    pub priority: Priority,
450    /// Description.
451    pub description: String,
452    /// Expected performance improvement.
453    pub expected_improvement: f64,
454    /// Implementation difficulty.
455    pub implementation_difficulty: ImplementationDifficulty,
456}
457
458/// Types of optimization recommendations.
459#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
460pub enum RecommendationType {
461    /// Memory layout optimization.
462    MemoryLayout,
463    /// Algorithm change recommendation.
464    AlgorithmChange,
465    /// Data structure change recommendation.
466    DataStructureChange,
467    /// Caching strategy recommendation.
468    CachingStrategy,
469    /// Memory pooling recommendation.
470    MemoryPooling,
471    /// Lazy initialization recommendation.
472    LazyInitialization,
473    /// Inlining recommendation.
474    Inlining,
475    /// Vectorization recommendation.
476    Vectorization,
477    /// Parallelization recommendation.
478    Parallelization,
479}
480
481/// Priority levels.
482#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
483pub enum Priority {
484    /// Low priority.
485    Low,
486    /// Medium priority.
487    Medium,
488    /// High priority.
489    High,
490    /// Critical priority.
491    Critical,
492}
493
494/// Implementation difficulty levels.
495#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
496pub enum ImplementationDifficulty {
497    /// Easy implementation difficulty.
498    Easy,
499    /// Medium implementation difficulty.
500    Medium,
501    /// Hard implementation difficulty.
502    Hard,
503    /// Very hard implementation difficulty.
504    VeryHard,
505}
506
507// Custom Serialize implementation for AllocationInfo to handle thread::ThreadId
508impl 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
552// Custom Deserialize implementation for AllocationInfo due to complex field handling
553impl<'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        // Parse thread_id from string format, default to current thread if parsing fails
597        let thread_id = if !helper.thread_id.is_empty() {
598            // Try to parse the thread_id from format like "ThreadId(1234567890)"
599            // Since we can't reconstruct the actual ThreadId, we use the current thread
600            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    /// Create a new AllocationInfo instance with improved field enhancements.
643    ///
644    /// # Arguments
645    ///
646    /// * `ptr` - Memory address of the allocation
647    /// * `size` - Size of the allocation in bytes
648    ///
649    /// # Examples
650    ///
651    /// ```
652    /// use memscope_rs::capture::types::AllocationInfo;
653    ///
654    /// let info = AllocationInfo::new(0x1000, 1024);
655    /// assert_eq!(info.ptr, 0x1000);
656    /// assert_eq!(info.size, 1024);
657    /// assert!(info.is_active());
658    /// ```
659    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), // Default: 1ms (just allocated)
684            borrow_info: None,    // No borrow info available by default
685            clone_info: Some(CloneInfo {
686                clone_count: 0,
687                is_clone: false,
688                original_ptr: None,
689            }),
690            ownership_history_available: false, // Not available without tracking
691            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    /// Set source location (file and line) for this allocation.
710    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    /// Set smart pointer information for this allocation.
716    pub fn set_smart_pointer_info(&mut self, info: SmartPointerInfo) {
717        self.smart_pointer_info = Some(info);
718    }
719
720    /// Mark this allocation as deallocated with current timestamp.
721    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    /// Check if this allocation is still active (not deallocated).
731    pub fn is_active(&self) -> bool {
732        self.timestamp_dealloc.is_none()
733    }
734
735    /// Update allocation with type-specific enhancements.
736    ///
737    /// Detects common patterns for Rc/Arc, Vec, String, HashMap, and Box types.
738    pub fn enhance_with_type_info(&mut self, type_name: &str) {
739        // Update lifetime_ms with current elapsed time
740        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        // Detect reference counting types (Rc, Arc)
751        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        // Detect collections that are commonly borrowed
766        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        // Detect Box types
778        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/// Risk distribution analysis for memory allocations.
796#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
797pub struct RiskDistribution {
798    /// Low risk allocations count.
799    pub low_risk: usize,
800    /// Medium risk allocations count.
801    pub medium_risk: usize,
802    /// High risk allocations count.
803    pub high_risk: usize,
804    /// Critical risk allocations count.
805    pub critical_risk: usize,
806}
807
808// Implement From trait for converting from core::types to capture::types
809impl 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        // Test with Rc type
1017        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        // Test with Vec type
1023        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        // Test that it can be serialized
1054        let serialized = serde_json::to_string(&info);
1055        assert!(serialized.is_ok());
1056
1057        // Test that serialized data contains expected fields
1058        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}