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