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    /// Source of this data (captured or inferred)
40    #[serde(default)]
41    pub _source: Option<String>,
42    /// Confidence level for inferred data
43    #[serde(default)]
44    pub _confidence: Option<String>,
45}
46
47/// Enhanced cloning information for allocations.
48///
49/// Tracks clone operations including clone counts, original source
50/// tracking, and clone relationships.
51#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
52pub struct CloneInfo {
53    /// Number of times this object was cloned.
54    pub clone_count: usize,
55    /// Whether this allocation itself is a result of a clone.
56    pub is_clone: bool,
57    /// If is_clone is true, points to the original object's pointer.
58    pub original_ptr: Option<usize>,
59
60    /// Source of this data (captured or inferred)
61    #[serde(default)]
62    pub _source: Option<String>,
63    /// Confidence level for inferred data
64    #[serde(default)]
65    pub _confidence: Option<String>,
66}
67
68/// Information about a memory allocation.
69///
70/// Comprehensive tracking information for a single memory allocation,
71/// including size, type, scope, lifecycle, and various analysis metadata.
72#[derive(Debug, Clone, PartialEq)]
73pub struct AllocationInfo {
74    /// Memory address of the allocation.
75    pub ptr: usize,
76    /// Size of the allocation in bytes.
77    pub size: usize,
78    /// Optional variable name associated with this allocation.
79    pub var_name: Option<String>,
80    /// Optional type name of the allocated data.
81    pub type_name: Option<String>,
82    /// Optional scope name where the allocation occurred.
83    pub scope_name: Option<String>,
84    /// Timestamp when the allocation was made.
85    pub timestamp_alloc: u64,
86    /// Optional timestamp when the allocation was deallocated.
87    pub timestamp_dealloc: Option<u64>,
88    /// Thread ID where the allocation occurred.
89    pub thread_id: thread::ThreadId,
90    /// Thread ID as u64 (original value from tracking).
91    pub thread_id_u64: u64,
92    /// Number of active borrows for this allocation.
93    pub borrow_count: usize,
94    /// Optional stack trace at the time of allocation.
95    pub stack_trace: Option<Vec<String>>,
96    /// Whether this allocation is considered leaked.
97    pub is_leaked: bool,
98    /// Precise lifetime in milliseconds (calculated from creation to destruction).
99    pub lifetime_ms: Option<u64>,
100    /// Enhanced borrowing information.
101    pub borrow_info: Option<BorrowInfo>,
102    /// Enhanced cloning information.
103    pub clone_info: Option<CloneInfo>,
104    /// Flag indicating if detailed ownership history is available in lifetime.json.
105    pub ownership_history_available: bool,
106    /// Smart pointer specific information.
107    pub smart_pointer_info: Option<SmartPointerInfo>,
108    /// Detailed memory layout information.
109    pub memory_layout: Option<MemoryLayoutInfo>,
110    /// Module path (from module_path!())
111    pub module_path: Option<String>,
112    /// Stack pointer (for StackOwner types like Arc/Rc)
113    pub stack_ptr: Option<usize>,
114    /// Task ID (for task-aware memory tracking)
115    pub task_id: Option<u64>,
116    /// Generic type information.
117    pub generic_info: Option<GenericTypeInfo>,
118    /// Dynamic type information (trait objects).
119    pub dynamic_type_info: Option<DynamicTypeInfo>,
120    /// Runtime state information.
121    pub runtime_state: Option<RuntimeStateInfo>,
122    /// Stack allocation information (if allocated on stack).
123    pub stack_allocation: Option<StackAllocationInfo>,
124    /// Temporary object information (if this is a temporary).
125    pub temporary_object: Option<TemporaryObjectInfo>,
126    /// Memory fragmentation analysis.
127    pub fragmentation_analysis: Option<EnhancedFragmentationAnalysis>,
128    /// Enhanced generic instantiation tracking.
129    pub generic_instantiation: Option<GenericInstantiationInfo>,
130    /// Type relationship information.
131    pub type_relationships: Option<TypeRelationshipInfo>,
132    /// Type usage information.
133    pub type_usage: Option<TypeUsageInfo>,
134    /// Function call tracking (if allocation is function-related).
135    pub function_call_tracking: Option<FunctionCallTrackingInfo>,
136    /// Object lifecycle tracking.
137    pub lifecycle_tracking: Option<ObjectLifecycleInfo>,
138    /// Memory access pattern tracking.
139    pub access_tracking: Option<MemoryAccessTrackingInfo>,
140    /// Drop chain analysis (when object is dropped).
141    pub drop_chain_analysis: Option<DropChainAnalysis>,
142}
143
144impl From<crate::core::types::AllocationInfo> for AllocationInfo {
145    fn from(old: crate::core::types::AllocationInfo) -> Self {
146        // For thread_id, we use a default value since ThreadId cannot be reliably reconstructed from String
147        // In a production system, this would require proper thread ID tracking
148        let thread_id = thread::current().id();
149
150        // Convert borrow_info
151        let borrow_info = old.borrow_info.map(|b| BorrowInfo {
152            immutable_borrows: b.immutable_borrows,
153            mutable_borrows: b.mutable_borrows,
154            max_concurrent_borrows: b.max_concurrent_borrows,
155            last_borrow_timestamp: b.last_borrow_timestamp,
156            _source: None,
157            _confidence: None,
158        });
159
160        // Convert clone_info
161        let clone_info = old.clone_info.map(|c| CloneInfo {
162            clone_count: c.clone_count,
163            is_clone: c.is_clone,
164            original_ptr: c.original_ptr,
165            _source: None,
166            _confidence: None,
167        });
168
169        // For complex nested types, we set them to None to avoid complex conversions
170        // In a production system, these would need proper conversion implementations
171        let smart_pointer_info =
172            old.smart_pointer_info
173                .map(|s| super::smart_pointer::SmartPointerInfo {
174                    data_ptr: s.data_ptr,
175                    cloned_from: s.cloned_from,
176                    clones: s.clones,
177                    ref_count_history: s
178                        .ref_count_history
179                        .iter()
180                        .map(|r| super::smart_pointer::RefCountSnapshot {
181                            timestamp: r.timestamp,
182                            strong_count: r.strong_count,
183                            weak_count: r.weak_count,
184                        })
185                        .collect(),
186                    weak_count: s.weak_count,
187                    is_weak_reference: s.is_weak_reference,
188                    is_data_owner: s.is_data_owner,
189                    is_implicitly_deallocated: s.is_implicitly_deallocated,
190                    pointer_type: match s.pointer_type {
191                        crate::core::types::SmartPointerType::Rc => {
192                            super::smart_pointer::SmartPointerType::Rc
193                        }
194                        crate::core::types::SmartPointerType::Arc => {
195                            super::smart_pointer::SmartPointerType::Arc
196                        }
197                        crate::core::types::SmartPointerType::RcWeak => {
198                            super::smart_pointer::SmartPointerType::RcWeak
199                        }
200                        crate::core::types::SmartPointerType::ArcWeak => {
201                            super::smart_pointer::SmartPointerType::ArcWeak
202                        }
203                        crate::core::types::SmartPointerType::Box => {
204                            super::smart_pointer::SmartPointerType::Box
205                        }
206                    },
207                });
208
209        Self {
210            ptr: old.ptr,
211            size: old.size,
212            var_name: old.var_name,
213            type_name: old.type_name,
214            scope_name: old.scope_name,
215            timestamp_alloc: old.timestamp_alloc,
216            timestamp_dealloc: old.timestamp_dealloc,
217            thread_id,
218            thread_id_u64: old.thread_id.parse().unwrap_or_else(|_| {
219                tracing::warn!(
220                    "Failed to parse thread_id: '{}', defaulting to 0",
221                    old.thread_id
222                );
223                0
224            }),
225            borrow_count: old.borrow_count,
226            stack_trace: old.stack_trace,
227            is_leaked: old.is_leaked,
228            lifetime_ms: old.lifetime_ms,
229            borrow_info,
230            clone_info,
231            ownership_history_available: old.ownership_history_available,
232            smart_pointer_info,
233            // Complex nested types - use Into::into for complete conversion
234            memory_layout: old.memory_layout.map(Into::into),
235            generic_info: old.generic_info.map(Into::into),
236            dynamic_type_info: old.dynamic_type_info.map(Into::into),
237            runtime_state: old.runtime_state.map(Into::into),
238            stack_allocation: old.stack_allocation.map(Into::into),
239            temporary_object: old.temporary_object.map(Into::into),
240            fragmentation_analysis: old.fragmentation_analysis.map(Into::into),
241            generic_instantiation: old.generic_instantiation.map(Into::into),
242            type_relationships: old.type_relationships.map(Into::into),
243            type_usage: old.type_usage.map(Into::into),
244            function_call_tracking: old.function_call_tracking.map(Into::into),
245            lifecycle_tracking: old.lifecycle_tracking.map(Into::into),
246            access_tracking: old.access_tracking.map(Into::into),
247            drop_chain_analysis: old.drop_chain_analysis.map(Into::into),
248            module_path: None, // core::types::AllocationInfo doesn't have module_path
249            stack_ptr: None,
250            task_id: None,
251        }
252    }
253}
254
255impl From<crate::capture::backends::core_types::AllocationInfo> for AllocationInfo {
256    fn from(info: crate::capture::backends::core_types::AllocationInfo) -> Self {
257        Self {
258            ptr: info.ptr,
259            size: info.size,
260            var_name: info.var_name,
261            type_name: info.type_name,
262            scope_name: None,
263            timestamp_alloc: info.allocated_at_ns,
264            timestamp_dealloc: None,
265            thread_id: std::thread::current().id(),
266            thread_id_u64: info.thread_id,
267            borrow_count: 0,
268            stack_trace: info.stack_trace,
269            is_leaked: false,
270            lifetime_ms: None,
271            module_path: None,
272            borrow_info: None,
273            clone_info: None,
274            ownership_history_available: false,
275            smart_pointer_info: None,
276            memory_layout: None,
277            generic_info: None,
278            dynamic_type_info: None,
279            runtime_state: None,
280            stack_allocation: None,
281            temporary_object: None,
282            fragmentation_analysis: None,
283            generic_instantiation: None,
284            type_relationships: None,
285            type_usage: None,
286            function_call_tracking: None,
287            lifecycle_tracking: None,
288            access_tracking: None,
289            drop_chain_analysis: None,
290            stack_ptr: None,
291            task_id: None,
292        }
293    }
294}
295
296/// Type usage information for tracking how types are used across the codebase.
297#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
298pub struct TypeUsageInfo {
299    /// Type name.
300    pub type_name: String,
301    /// Total usage count.
302    pub total_usage_count: u64,
303    /// Usage contexts.
304    pub usage_contexts: Vec<UsageContext>,
305    /// Usage patterns over time.
306    pub usage_timeline: Vec<UsageTimePoint>,
307    /// Hot paths where type is used.
308    pub hot_paths: Vec<HotPath>,
309    /// Performance impact of usage.
310    pub performance_impact: TypePerformanceImpact,
311}
312
313/// Usage context information.
314#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
315pub struct UsageContext {
316    /// Context type.
317    pub context_type: ContextType,
318    /// Function or module name.
319    pub location: String,
320    /// Usage frequency in this context.
321    pub frequency: u32,
322    /// Performance characteristics in this context.
323    pub performance_metrics: ContextPerformanceMetrics,
324}
325
326/// Context types where types are used.
327#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
328pub enum ContextType {
329    /// Function parameter context.
330    FunctionParameter,
331    /// Function return context.
332    FunctionReturn,
333    /// Local variable context.
334    LocalVariable,
335    /// Struct field context.
336    StructField,
337    /// Enum variant context.
338    EnumVariant,
339    /// Trait method context.
340    TraitMethod,
341    /// Generic constraint context.
342    GenericConstraint,
343    /// Closure capture context.
344    ClosureCapture,
345    /// Async context.
346    AsyncContext,
347    /// Unsafe context.
348    UnsafeContext,
349}
350
351/// Performance metrics within specific contexts.
352#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
353pub struct ContextPerformanceMetrics {
354    /// Average execution time in this context.
355    pub avg_execution_time_ns: f64,
356    /// Memory allocation frequency.
357    pub allocation_frequency: f64,
358    /// Cache miss rate in this context.
359    pub cache_miss_rate: f64,
360    /// Branch misprediction rate.
361    pub branch_misprediction_rate: f64,
362}
363
364/// Usage time point for timeline analysis.
365#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
366pub struct UsageTimePoint {
367    /// Timestamp.
368    pub timestamp: u64,
369    /// Usage count at this time.
370    pub usage_count: u32,
371    /// Memory usage at this time.
372    pub memory_usage: usize,
373    /// Performance metrics at this time.
374    pub performance_snapshot: PerformanceSnapshot,
375}
376
377/// Performance snapshot at a specific time.
378#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
379pub struct PerformanceSnapshot {
380    /// CPU usage percentage.
381    pub cpu_usage: f64,
382    /// Memory usage percentage.
383    pub memory_usage: f64,
384    /// Cache hit rate.
385    pub cache_hit_rate: f64,
386    /// Throughput (operations per second).
387    pub throughput: f64,
388}
389
390/// Hot path information.
391#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
392pub struct HotPath {
393    /// Path identifier.
394    pub path_id: String,
395    /// Function call sequence.
396    pub call_sequence: Vec<String>,
397    /// Execution frequency.
398    pub execution_frequency: u64,
399    /// Total execution time.
400    pub total_execution_time_ns: u64,
401    /// Average execution time.
402    pub avg_execution_time_ns: f64,
403    /// Memory allocations in this path.
404    pub memory_allocations: u32,
405    /// Performance bottlenecks.
406    pub bottlenecks: Vec<PerformanceBottleneck>,
407}
408
409/// Performance bottleneck information.
410#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
411pub struct PerformanceBottleneck {
412    /// Bottleneck type.
413    pub bottleneck_type: BottleneckType,
414    /// Location in code.
415    pub location: String,
416    /// Impact severity.
417    pub severity: ImpactLevel,
418    /// Description.
419    pub description: String,
420    /// Suggested optimization.
421    pub optimization_suggestion: String,
422}
423
424/// Types of performance bottlenecks.
425#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
426pub enum BottleneckType {
427    /// Memory allocation bottleneck.
428    MemoryAllocation,
429    /// Memory deallocation bottleneck.
430    MemoryDeallocation,
431    /// Cache miss bottleneck.
432    CacheMiss,
433    /// Branch misprediction bottleneck.
434    BranchMisprediction,
435    /// Function call bottleneck.
436    FunctionCall,
437    /// Data movement bottleneck.
438    DataMovement,
439    /// Synchronization bottleneck.
440    Synchronization,
441    /// I/O bottleneck.
442    IO,
443}
444
445/// Impact level enumeration.
446#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
447pub enum ImpactLevel {
448    /// Low impact level.
449    Low,
450    /// Medium impact level.
451    Medium,
452    /// High impact level.
453    High,
454    /// Critical impact level.
455    Critical,
456}
457
458/// Type performance impact assessment.
459#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
460pub struct TypePerformanceImpact {
461    /// Overall performance score (0-100).
462    pub performance_score: f64,
463    /// Memory efficiency score (0-100).
464    pub memory_efficiency_score: f64,
465    /// CPU efficiency score (0-100).
466    pub cpu_efficiency_score: f64,
467    /// Cache efficiency score (0-100).
468    pub cache_efficiency_score: f64,
469    /// Optimization recommendations.
470    pub optimization_recommendations: Vec<OptimizationRecommendation>,
471}
472
473/// Optimization recommendation.
474#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
475pub struct OptimizationRecommendation {
476    /// Recommendation type.
477    pub recommendation_type: RecommendationType,
478    /// Priority level.
479    pub priority: Priority,
480    /// Description.
481    pub description: String,
482    /// Expected performance improvement.
483    pub expected_improvement: f64,
484    /// Implementation difficulty.
485    pub implementation_difficulty: ImplementationDifficulty,
486}
487
488/// Types of optimization recommendations.
489#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
490pub enum RecommendationType {
491    /// Memory layout optimization.
492    MemoryLayout,
493    /// Algorithm change recommendation.
494    AlgorithmChange,
495    /// Data structure change recommendation.
496    DataStructureChange,
497    /// Caching strategy recommendation.
498    CachingStrategy,
499    /// Memory pooling recommendation.
500    MemoryPooling,
501    /// Lazy initialization recommendation.
502    LazyInitialization,
503    /// Inlining recommendation.
504    Inlining,
505    /// Vectorization recommendation.
506    Vectorization,
507    /// Parallelization recommendation.
508    Parallelization,
509}
510
511/// Priority levels.
512#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
513pub enum Priority {
514    /// Low priority.
515    Low,
516    /// Medium priority.
517    Medium,
518    /// High priority.
519    High,
520    /// Critical priority.
521    Critical,
522}
523
524/// Implementation difficulty levels.
525#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
526pub enum ImplementationDifficulty {
527    /// Easy implementation difficulty.
528    Easy,
529    /// Medium implementation difficulty.
530    Medium,
531    /// Hard implementation difficulty.
532    Hard,
533    /// Very hard implementation difficulty.
534    VeryHard,
535}
536
537// Custom Serialize implementation for AllocationInfo to handle thread::ThreadId
538impl Serialize for AllocationInfo {
539    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
540    where
541        S: serde::Serializer,
542    {
543        use serde::ser::SerializeStruct;
544        let mut state = serializer.serialize_struct("AllocationInfo", 25)?;
545        state.serialize_field("ptr", &self.ptr)?;
546        state.serialize_field("size", &self.size)?;
547        state.serialize_field("var_name", &self.var_name)?;
548        state.serialize_field("type_name", &self.type_name)?;
549        state.serialize_field("scope_name", &self.scope_name)?;
550        state.serialize_field("timestamp_alloc", &self.timestamp_alloc)?;
551        state.serialize_field("timestamp_dealloc", &self.timestamp_dealloc)?;
552        state.serialize_field("thread_id", &format!("{:?}", self.thread_id))?;
553        state.serialize_field("borrow_count", &self.borrow_count)?;
554        state.serialize_field("stack_trace", &self.stack_trace)?;
555        state.serialize_field("is_leaked", &self.is_leaked)?;
556        state.serialize_field("lifetime_ms", &self.lifetime_ms)?;
557        state.serialize_field("borrow_info", &self.borrow_info)?;
558        state.serialize_field("clone_info", &self.clone_info)?;
559        state.serialize_field(
560            "ownership_history_available",
561            &self.ownership_history_available,
562        )?;
563        state.serialize_field("smart_pointer_info", &self.smart_pointer_info)?;
564        state.serialize_field("memory_layout", &self.memory_layout)?;
565        state.serialize_field("generic_info", &self.generic_info)?;
566        state.serialize_field("dynamic_type_info", &self.dynamic_type_info)?;
567        state.serialize_field("runtime_state", &self.runtime_state)?;
568        state.serialize_field("stack_allocation", &self.stack_allocation)?;
569        state.serialize_field("temporary_object", &self.temporary_object)?;
570        state.serialize_field("fragmentation_analysis", &self.fragmentation_analysis)?;
571        state.serialize_field("generic_instantiation", &self.generic_instantiation)?;
572        state.serialize_field("type_relationships", &self.type_relationships)?;
573        state.serialize_field("type_usage", &self.type_usage)?;
574        state.serialize_field("function_call_tracking", &self.function_call_tracking)?;
575        state.serialize_field("lifecycle_tracking", &self.lifecycle_tracking)?;
576        state.serialize_field("access_tracking", &self.access_tracking)?;
577        state.serialize_field("drop_chain_analysis", &self.drop_chain_analysis)?;
578        state.serialize_field("module_path", &self.module_path)?;
579        state.end()
580    }
581}
582
583// Custom Deserialize implementation for AllocationInfo due to complex field handling
584impl<'de> Deserialize<'de> for AllocationInfo {
585    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
586    where
587        D: serde::Deserializer<'de>,
588    {
589        #[derive(Deserialize)]
590        struct AllocationInfoHelper {
591            ptr: usize,
592            size: usize,
593            var_name: Option<String>,
594            type_name: Option<String>,
595            scope_name: Option<String>,
596            timestamp_alloc: u64,
597            timestamp_dealloc: Option<u64>,
598            #[serde(default)]
599            thread_id: String,
600            #[serde(default)]
601            thread_id_u64: u64,
602            borrow_count: usize,
603            stack_trace: Option<Vec<String>>,
604            is_leaked: bool,
605            lifetime_ms: Option<u64>,
606            borrow_info: Option<BorrowInfo>,
607            clone_info: Option<CloneInfo>,
608            ownership_history_available: Option<bool>,
609            smart_pointer_info: Option<SmartPointerInfo>,
610            memory_layout: Option<MemoryLayoutInfo>,
611            generic_info: Option<GenericTypeInfo>,
612            dynamic_type_info: Option<DynamicTypeInfo>,
613            runtime_state: Option<RuntimeStateInfo>,
614            stack_allocation: Option<StackAllocationInfo>,
615            temporary_object: Option<TemporaryObjectInfo>,
616            fragmentation_analysis: Option<EnhancedFragmentationAnalysis>,
617            generic_instantiation: Option<GenericInstantiationInfo>,
618            type_relationships: Option<TypeRelationshipInfo>,
619            type_usage: Option<TypeUsageInfo>,
620            function_call_tracking: Option<FunctionCallTrackingInfo>,
621            lifecycle_tracking: Option<ObjectLifecycleInfo>,
622            access_tracking: Option<MemoryAccessTrackingInfo>,
623            drop_chain_analysis: Option<DropChainAnalysis>,
624            module_path: Option<String>,
625        }
626
627        let helper = AllocationInfoHelper::deserialize(deserializer)?;
628        // Parse thread_id from string format, default to current thread if parsing fails
629        let thread_id = if !helper.thread_id.is_empty() {
630            // Try to parse the thread_id from format like "ThreadId(1234567890)"
631            // Since we can't reconstruct the actual ThreadId, we use the current thread
632            thread::current().id()
633        } else {
634            thread::current().id()
635        };
636
637        Ok(AllocationInfo {
638            ptr: helper.ptr,
639            size: helper.size,
640            var_name: helper.var_name,
641            type_name: helper.type_name,
642            scope_name: helper.scope_name,
643            timestamp_alloc: helper.timestamp_alloc,
644            timestamp_dealloc: helper.timestamp_dealloc,
645            thread_id,
646            thread_id_u64: helper.thread_id_u64,
647            borrow_count: helper.borrow_count,
648            stack_trace: helper.stack_trace,
649            is_leaked: helper.is_leaked,
650            lifetime_ms: helper.lifetime_ms,
651            borrow_info: helper.borrow_info,
652            clone_info: helper.clone_info,
653            ownership_history_available: helper.ownership_history_available.unwrap_or(false),
654            smart_pointer_info: helper.smart_pointer_info,
655            memory_layout: helper.memory_layout,
656            generic_info: helper.generic_info,
657            dynamic_type_info: helper.dynamic_type_info,
658            runtime_state: helper.runtime_state,
659            stack_allocation: helper.stack_allocation,
660            temporary_object: helper.temporary_object,
661            fragmentation_analysis: helper.fragmentation_analysis,
662            generic_instantiation: helper.generic_instantiation,
663            type_relationships: helper.type_relationships,
664            type_usage: helper.type_usage,
665            function_call_tracking: helper.function_call_tracking,
666            lifecycle_tracking: helper.lifecycle_tracking,
667            access_tracking: helper.access_tracking,
668            drop_chain_analysis: helper.drop_chain_analysis,
669            module_path: helper.module_path,
670            stack_ptr: None,
671            task_id: None,
672        })
673    }
674}
675
676impl AllocationInfo {
677    /// Create a new AllocationInfo instance with improved field enhancements.
678    ///
679    /// # Arguments
680    ///
681    /// * `ptr` - Memory address of the allocation
682    /// * `size` - Size of the allocation in bytes
683    ///
684    /// # Examples
685    ///
686    /// ```
687    /// use memscope_rs::capture::types::AllocationInfo;
688    ///
689    /// let info = AllocationInfo::new(0x1000, 1024);
690    /// assert_eq!(info.ptr, 0x1000);
691    /// assert_eq!(info.size, 1024);
692    /// assert!(info.is_active());
693    /// ```
694    pub fn new(ptr: usize, size: usize) -> Self {
695        // Record allocation in task registry
696        crate::task_registry::global_registry().record_allocation(size);
697
698        let timestamp = std::time::SystemTime::now()
699            .duration_since(std::time::UNIX_EPOCH)
700            .unwrap_or_default()
701            .as_nanos() as u64;
702
703        Self {
704            ptr,
705            size,
706            var_name: None,
707            type_name: None,
708            scope_name: None,
709            timestamp_alloc: timestamp,
710            timestamp_dealloc: None,
711            thread_id: thread::current().id(),
712            thread_id_u64: {
713                use std::hash::{Hash, Hasher};
714                let mut hasher = std::collections::hash_map::DefaultHasher::new();
715                thread::current().id().hash(&mut hasher);
716                hasher.finish()
717            },
718            borrow_count: 0,
719            stack_trace: None,
720            is_leaked: false,
721            lifetime_ms: Some(1), // Default: 1ms (just allocated)
722            borrow_info: None,    // No borrow info available by default
723            clone_info: Some(CloneInfo {
724                clone_count: 0,
725                is_clone: false,
726                original_ptr: None,
727                _source: None,
728                _confidence: None,
729            }),
730            ownership_history_available: false, // Not available without tracking
731            smart_pointer_info: None,
732            memory_layout: None,
733            generic_info: None,
734            dynamic_type_info: None,
735            runtime_state: None,
736            stack_allocation: None,
737            temporary_object: None,
738            fragmentation_analysis: None,
739            generic_instantiation: None,
740            type_relationships: None,
741            type_usage: None,
742            function_call_tracking: None,
743            lifecycle_tracking: None,
744            access_tracking: None,
745            drop_chain_analysis: None,
746            module_path: None,
747            stack_ptr: None,
748            task_id: crate::task_registry::TaskIdRegistry::current_task_id(),
749        }
750    }
751
752    /// Set source location (file and line) for this allocation.
753    pub fn set_source_location(&mut self, file: &str, line: u32) {
754        let frame = format!("{}:{}", file, line);
755        self.stack_trace.get_or_insert_with(Vec::new).push(frame);
756    }
757
758    /// Set smart pointer information for this allocation.
759    pub fn set_smart_pointer_info(&mut self, info: SmartPointerInfo) {
760        self.smart_pointer_info = Some(info);
761    }
762
763    /// Mark this allocation as deallocated with current timestamp.
764    pub fn mark_deallocated(&mut self) {
765        self.timestamp_dealloc = Some(
766            std::time::SystemTime::now()
767                .duration_since(std::time::UNIX_EPOCH)
768                .unwrap_or_default()
769                .as_nanos() as u64,
770        );
771    }
772
773    /// Check if this allocation is still active (not deallocated).
774    pub fn is_active(&self) -> bool {
775        self.timestamp_dealloc.is_none()
776    }
777
778    /// Update allocation with type-specific enhancements using inference engine.
779    ///
780    /// ⚠️ WARNING: This method uses inference/heuristics. Data may be WRONG.
781    /// All inferred data is marked with `_source: "inferred"` and confidence level.
782    ///
783    /// Detects common patterns for Rc/Arc, Vec, String, HashMap, and Box types.
784    pub fn enhance_with_type_info(&mut self, type_name: &str) {
785        if self.timestamp_dealloc.is_none() {
786            let current_time = std::time::SystemTime::now()
787                .duration_since(std::time::UNIX_EPOCH)
788                .unwrap_or_default()
789                .as_nanos() as u64;
790            let elapsed_ns = current_time.saturating_sub(self.timestamp_alloc);
791            let elapsed_ms = elapsed_ns / 1_000_000;
792            self.lifetime_ms = Some(if elapsed_ms == 0 { 1 } else { elapsed_ms });
793        }
794
795        // Use inference engine for borrow and clone info
796        // ⚠️ All data below is INFERRED, not captured
797        if type_name.contains("Rc<") || type_name.contains("Arc<") {
798            self.clone_info = Some(CloneInfo {
799                clone_count: 2,
800                is_clone: false,
801                original_ptr: None,
802                _source: Some("inferred".to_string()),
803                _confidence: Some("low".to_string()),
804            });
805
806            self.borrow_info = Some(BorrowInfo {
807                immutable_borrows: 5,
808                mutable_borrows: 0,
809                max_concurrent_borrows: 5,
810                last_borrow_timestamp: Some(self.timestamp_alloc + 1000000),
811                _source: Some("inferred".to_string()),
812                _confidence: Some("low".to_string()),
813            });
814        } else if type_name.contains("Vec<")
815            || type_name.contains("String")
816            || type_name.contains("HashMap")
817        {
818            self.borrow_info = Some(BorrowInfo {
819                immutable_borrows: 4,
820                mutable_borrows: 2,
821                max_concurrent_borrows: 3,
822                last_borrow_timestamp: Some(self.timestamp_alloc + 800000),
823                _source: Some("inferred".to_string()),
824                _confidence: Some("low".to_string()),
825            });
826        } else if type_name.contains("Box<") {
827            self.clone_info = Some(CloneInfo {
828                clone_count: 0,
829                is_clone: false,
830                original_ptr: None,
831                _source: Some("inferred".to_string()),
832                _confidence: Some("low".to_string()),
833            });
834
835            self.borrow_info = Some(BorrowInfo {
836                immutable_borrows: 2,
837                mutable_borrows: 1,
838                max_concurrent_borrows: 1,
839                last_borrow_timestamp: Some(self.timestamp_alloc + 300000),
840                _source: Some("inferred".to_string()),
841                _confidence: Some("low".to_string()),
842            });
843        }
844    }
845
846    /// Enhance with inference engine (explicit inference)
847    ///
848    /// ⚠️ WARNING: All data from this method is INFERRED.
849    pub fn enhance_with_inference(&mut self, engine: &crate::capture::inference::InferenceEngine) {
850        let type_name = self.type_name.as_deref();
851
852        let inferred_borrow = engine.infer_borrow_info(type_name);
853        self.borrow_info = Some(BorrowInfo {
854            immutable_borrows: inferred_borrow.immutable_borrows,
855            mutable_borrows: inferred_borrow.mutable_borrows,
856            max_concurrent_borrows: inferred_borrow.max_concurrent_borrows,
857            last_borrow_timestamp: None,
858            _source: Some("inferred".to_string()),
859            _confidence: Some(format!("{:?}", inferred_borrow._confidence).to_lowercase()),
860        });
861
862        let inferred_sp = engine.infer_smart_pointer(type_name);
863        if inferred_sp.pointer_type != crate::capture::inference::SmartPointerType::Unknown {
864            self.clone_info = Some(CloneInfo {
865                clone_count: inferred_sp.ref_count.unwrap_or(0),
866                is_clone: false,
867                original_ptr: None,
868                _source: Some("inferred".to_string()),
869                _confidence: Some(format!("{:?}", inferred_sp._confidence).to_lowercase()),
870            });
871        }
872    }
873}
874
875/// Risk distribution analysis for memory allocations.
876#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
877pub struct RiskDistribution {
878    /// Low risk allocations count.
879    pub low_risk: usize,
880    /// Medium risk allocations count.
881    pub medium_risk: usize,
882    /// High risk allocations count.
883    pub high_risk: usize,
884    /// Critical risk allocations count.
885    pub critical_risk: usize,
886}
887
888// Implement From trait for converting from core::types to capture::types
889impl From<crate::core::types::TypeUsageInfo> for TypeUsageInfo {
890    fn from(old: crate::core::types::TypeUsageInfo) -> Self {
891        Self {
892            type_name: old.type_name,
893            total_usage_count: old.total_usage_count,
894            usage_contexts: old
895                .usage_contexts
896                .into_iter()
897                .map(|c| UsageContext {
898                    context_type: match c.context_type {
899                        crate::core::types::ContextType::FunctionParameter => {
900                            ContextType::FunctionParameter
901                        }
902                        crate::core::types::ContextType::FunctionReturn => {
903                            ContextType::FunctionReturn
904                        }
905                        crate::core::types::ContextType::LocalVariable => {
906                            ContextType::LocalVariable
907                        }
908                        crate::core::types::ContextType::StructField => ContextType::StructField,
909                        crate::core::types::ContextType::EnumVariant => ContextType::EnumVariant,
910                        crate::core::types::ContextType::TraitMethod => ContextType::TraitMethod,
911                        crate::core::types::ContextType::GenericConstraint => {
912                            ContextType::GenericConstraint
913                        }
914                        crate::core::types::ContextType::ClosureCapture => {
915                            ContextType::ClosureCapture
916                        }
917                        crate::core::types::ContextType::AsyncContext => ContextType::AsyncContext,
918                        crate::core::types::ContextType::UnsafeContext => {
919                            ContextType::UnsafeContext
920                        }
921                    },
922                    location: c.location,
923                    frequency: c.frequency,
924                    performance_metrics: ContextPerformanceMetrics {
925                        avg_execution_time_ns: c.performance_metrics.avg_execution_time_ns,
926                        allocation_frequency: c.performance_metrics.allocation_frequency,
927                        cache_miss_rate: c.performance_metrics.cache_miss_rate,
928                        branch_misprediction_rate: c.performance_metrics.branch_misprediction_rate,
929                    },
930                })
931                .collect(),
932            usage_timeline: old
933                .usage_timeline
934                .into_iter()
935                .map(|t| UsageTimePoint {
936                    timestamp: t.timestamp,
937                    usage_count: t.usage_count,
938                    memory_usage: t.memory_usage,
939                    performance_snapshot: PerformanceSnapshot {
940                        cpu_usage: t.performance_snapshot.cpu_usage,
941                        memory_usage: t.performance_snapshot.memory_usage,
942                        cache_hit_rate: t.performance_snapshot.cache_hit_rate,
943                        throughput: t.performance_snapshot.throughput,
944                    },
945                })
946                .collect(),
947            hot_paths: old
948                .hot_paths
949                .into_iter()
950                .map(|h| HotPath {
951                    path_id: h.path_id,
952                    call_sequence: h.call_sequence,
953                    execution_frequency: h.execution_frequency,
954                    total_execution_time_ns: h.total_execution_time_ns,
955                    avg_execution_time_ns: h.avg_execution_time_ns,
956                    memory_allocations: h.memory_allocations,
957                    bottlenecks: h
958                        .bottlenecks
959                        .into_iter()
960                        .map(|b| PerformanceBottleneck {
961                            bottleneck_type: match b.bottleneck_type {
962                                crate::core::types::BottleneckType::MemoryAllocation => {
963                                    BottleneckType::MemoryAllocation
964                                }
965                                crate::core::types::BottleneckType::MemoryDeallocation => {
966                                    BottleneckType::MemoryDeallocation
967                                }
968                                crate::core::types::BottleneckType::CacheMiss => {
969                                    BottleneckType::CacheMiss
970                                }
971                                crate::core::types::BottleneckType::BranchMisprediction => {
972                                    BottleneckType::BranchMisprediction
973                                }
974                                crate::core::types::BottleneckType::FunctionCall => {
975                                    BottleneckType::FunctionCall
976                                }
977                                crate::core::types::BottleneckType::DataMovement => {
978                                    BottleneckType::DataMovement
979                                }
980                                crate::core::types::BottleneckType::Synchronization => {
981                                    BottleneckType::Synchronization
982                                }
983                                crate::core::types::BottleneckType::IO => BottleneckType::IO,
984                            },
985                            location: b.location,
986                            severity: match b.severity {
987                                crate::core::types::ImpactLevel::Low => ImpactLevel::Low,
988                                crate::core::types::ImpactLevel::Medium => ImpactLevel::Medium,
989                                crate::core::types::ImpactLevel::High => ImpactLevel::High,
990                                crate::core::types::ImpactLevel::Critical => ImpactLevel::Critical,
991                            },
992                            description: b.description,
993                            optimization_suggestion: b.optimization_suggestion,
994                        })
995                        .collect(),
996                })
997                .collect(),
998            performance_impact: TypePerformanceImpact {
999                performance_score: old.performance_impact.performance_score,
1000                memory_efficiency_score: old.performance_impact.memory_efficiency_score,
1001                cpu_efficiency_score: old.performance_impact.cpu_efficiency_score,
1002                cache_efficiency_score: old.performance_impact.cache_efficiency_score,
1003                optimization_recommendations: old
1004                    .performance_impact
1005                    .optimization_recommendations
1006                    .into_iter()
1007                    .map(|r| OptimizationRecommendation {
1008                        recommendation_type: match r.recommendation_type {
1009                            crate::core::types::RecommendationType::MemoryLayout => {
1010                                RecommendationType::MemoryLayout
1011                            }
1012                            crate::core::types::RecommendationType::AlgorithmChange => {
1013                                RecommendationType::AlgorithmChange
1014                            }
1015                            crate::core::types::RecommendationType::DataStructureChange => {
1016                                RecommendationType::DataStructureChange
1017                            }
1018                            crate::core::types::RecommendationType::CachingStrategy => {
1019                                RecommendationType::CachingStrategy
1020                            }
1021                            crate::core::types::RecommendationType::MemoryPooling => {
1022                                RecommendationType::MemoryPooling
1023                            }
1024                            crate::core::types::RecommendationType::LazyInitialization => {
1025                                RecommendationType::LazyInitialization
1026                            }
1027                            crate::core::types::RecommendationType::Inlining => {
1028                                RecommendationType::Inlining
1029                            }
1030                            crate::core::types::RecommendationType::Vectorization => {
1031                                RecommendationType::Vectorization
1032                            }
1033                            crate::core::types::RecommendationType::Parallelization => {
1034                                RecommendationType::Parallelization
1035                            }
1036                        },
1037                        priority: match r.priority {
1038                            crate::core::types::Priority::Low => Priority::Low,
1039                            crate::core::types::Priority::Medium => Priority::Medium,
1040                            crate::core::types::Priority::High => Priority::High,
1041                            crate::core::types::Priority::Critical => Priority::Critical,
1042                        },
1043                        description: r.description,
1044                        expected_improvement: r.expected_improvement,
1045                        implementation_difficulty: match r.implementation_difficulty {
1046                            crate::core::types::ImplementationDifficulty::Easy => {
1047                                ImplementationDifficulty::Easy
1048                            }
1049                            crate::core::types::ImplementationDifficulty::Medium => {
1050                                ImplementationDifficulty::Medium
1051                            }
1052                            crate::core::types::ImplementationDifficulty::Hard => {
1053                                ImplementationDifficulty::Hard
1054                            }
1055                            crate::core::types::ImplementationDifficulty::VeryHard => {
1056                                ImplementationDifficulty::VeryHard
1057                            }
1058                        },
1059                    })
1060                    .collect(),
1061            },
1062        }
1063    }
1064}
1065
1066#[cfg(test)]
1067mod tests {
1068    use super::*;
1069
1070    #[test]
1071    fn test_allocation_info_creation() {
1072        let info = AllocationInfo::new(0x12345678, 1024);
1073
1074        assert_eq!(info.ptr, 0x12345678);
1075        assert_eq!(info.size, 1024);
1076        assert!(info.is_active());
1077        assert!(info.borrow_info.is_none());
1078        assert!(info.clone_info.is_some());
1079        assert!(!info.ownership_history_available);
1080    }
1081
1082    #[test]
1083    fn test_allocation_info_mark_deallocated() {
1084        let mut info = AllocationInfo::new(0x1000, 512);
1085        assert!(info.is_active());
1086
1087        info.mark_deallocated();
1088        assert!(!info.is_active());
1089        assert!(info.timestamp_dealloc.is_some());
1090    }
1091
1092    #[test]
1093    fn test_allocation_info_enhance_with_type_info() {
1094        let mut info = AllocationInfo::new(0x1000, 512);
1095
1096        // Test with Rc type
1097        info.enhance_with_type_info("std::rc::Rc<String>");
1098        if let Some(clone_info) = &info.clone_info {
1099            assert_eq!(clone_info.clone_count, 2);
1100        }
1101
1102        // Test with Vec type
1103        info.enhance_with_type_info("Vec<i32>");
1104        if let Some(borrow_info) = &info.borrow_info {
1105            assert_eq!(borrow_info.immutable_borrows, 4);
1106            assert_eq!(borrow_info.mutable_borrows, 2);
1107        }
1108    }
1109
1110    #[test]
1111    fn test_borrow_info_default() {
1112        let borrow_info = BorrowInfo::default();
1113
1114        assert_eq!(borrow_info.immutable_borrows, 0);
1115        assert_eq!(borrow_info.mutable_borrows, 0);
1116        assert_eq!(borrow_info.max_concurrent_borrows, 0);
1117        assert_eq!(borrow_info.last_borrow_timestamp, None);
1118    }
1119
1120    #[test]
1121    fn test_clone_info_default() {
1122        let clone_info = CloneInfo::default();
1123
1124        assert_eq!(clone_info.clone_count, 0);
1125        assert!(!clone_info.is_clone);
1126        assert_eq!(clone_info.original_ptr, None);
1127    }
1128
1129    #[test]
1130    fn test_allocation_info_serialization() {
1131        let info = AllocationInfo::new(0x1000, 512);
1132
1133        // Test that it can be serialized
1134        let serialized = serde_json::to_string(&info);
1135        assert!(serialized.is_ok());
1136
1137        // Test that serialized data contains expected fields
1138        let json_str = serialized.expect("Failed to serialize AllocationInfo to JSON");
1139        assert!(json_str.contains("ptr"));
1140        assert!(json_str.contains("size"));
1141    }
1142}