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