Skip to main content

memscope_rs/
lib.rs

1//! Memory tracking and visualization tools for Rust applications.
2//!
3//! This crate provides tools for tracking memory allocations and visualizing
4//! memory usage in Rust applications. It includes a custom global allocator
5//! that tracks all heap allocations and deallocations, and provides utilities
6//! for exporting memory usage data in various formats.
7
8/// Advanced memory analysis functionality
9pub mod analysis;
10/// Analysis Engine - Memory analysis logic
11pub mod analysis_engine;
12/// Core memory tracking functionality
13pub mod core;
14
15pub mod capture;
16/// Event Store Engine - Centralized event storage
17pub mod event_store;
18/// Facade API - Unified user interface
19pub mod facade;
20/// Metadata Engine - Centralized metadata management
21pub mod metadata;
22/// Query Engine - Unified query interface
23pub mod query;
24/// Render Engine - Output rendering
25pub mod render_engine;
26/// Snapshot Engine - Snapshot construction and aggregation
27pub mod snapshot;
28/// Memory management utilities
29pub mod memory {
30    pub use crate::snapshot::memory::*;
31}
32/// Timeline Engine - Time-based memory analysis
33pub mod timeline;
34/// Unified Tracker API - Simple, unified interface for memory tracking
35pub mod tracker;
36
37// Export simplified global tracking API
38pub use capture::backends::global_tracking::{
39    global_tracker, init_global_tracking, init_global_tracking_with_config, is_initialized,
40    GlobalTracker, GlobalTrackerConfig, GlobalTrackerStats, TrackerConfig,
41};
42
43/// Unified error handling and recovery system
44pub mod error;
45/// Memory allocation tracking statistics and monitoring
46pub mod tracking;
47/// Utility functions
48pub mod utils;
49/// Variable registry for lightweight HashMap-based variable tracking
50pub mod variable_registry;
51
52pub use analysis::*;
53pub use capture::backends::bottleneck_analysis::{BottleneckKind, PerformanceIssue};
54pub use capture::backends::hotspot_analysis::{CallStackHotspot, MemoryUsagePeak};
55pub use capture::backends::{
56    configure_tracking_strategy, get_tracker as get_capture_tracker, AllocationCategory,
57    AnalysisSummary, AsyncAllocation, AsyncBackend, AsyncMemorySnapshot, AsyncSnapshot, AsyncStats,
58    AsyncTracker, CoreBackend, Event, EventType, FrequencyData, FrequencyPattern, InteractionType,
59    LockfreeAnalysis, LockfreeBackend, RuntimeEnvironment, SamplingConfig, SystemMetrics, TaskInfo,
60    TaskMemoryProfile, ThreadInteraction, ThreadLocalTracker, ThreadStats, TrackedFuture,
61    TrackingStrategy, UnifiedBackend,
62};
63pub use capture::backends::{
64    is_tracking, memory_snapshot, quick_trace, stop_tracing, trace_all, trace_thread,
65};
66pub use capture::types::{AllocationInfo, SmartPointerInfo, TrackingError, TrackingResult};
67pub use capture::{CaptureBackend, CaptureBackendType, CaptureEngine};
68pub use core::allocator::TrackingAllocator;
69pub use core::tracker::{get_tracker, MemoryTracker};
70pub use core::{ExportMode, ExportOptions};
71pub use core::{MemScopeError, MemScopeResult};
72#[cfg(feature = "derive")]
73pub use memscope_derive::Trackable;
74pub use snapshot::engine::SnapshotEngine;
75pub use snapshot::memory::{
76    BoundedHistory, BoundedHistoryConfig, BoundedHistoryStats, MemoryConfig, TimestampedEntry,
77};
78pub use snapshot::types::{ActiveAllocation, MemorySnapshot, MemoryStats, ThreadMemoryStats};
79/// Global tracking allocator instance - only enabled with tracking-allocator feature
80/// for single-threaded or low-concurrency applications.
81#[cfg(feature = "tracking-allocator")]
82#[global_allocator]
83pub static GLOBAL: TrackingAllocator = TrackingAllocator::new();
84/// Trait for types that can be tracked by the memory tracker.
85pub trait Trackable {
86    /// Get the pointer to the heap allocation for this value.
87    fn get_heap_ptr(&self) -> Option<usize>;
88    /// Get the type name for this value.
89    fn get_type_name(&self) -> &'static str;
90    /// Get estimated size of the allocation.
91    fn get_size_estimate(&self) -> usize;
92    /// Get reference count for smart pointers (Arc/Rc).
93    fn get_ref_count(&self) -> Option<usize> {
94        None
95    }
96    /// Get data pointer for smart pointers.
97    fn get_data_ptr(&self) -> Option<usize>;
98    /// Get the size of the pointed-to data.
99    fn get_data_size(&self) -> Option<usize>;
100}
101
102impl<T> Trackable for Vec<T> {
103    fn get_heap_ptr(&self) -> Option<usize> {
104        Some(self.as_ptr() as usize)
105    }
106    fn get_type_name(&self) -> &'static str {
107        "Vec<T>"
108    }
109    fn get_size_estimate(&self) -> usize {
110        std::mem::size_of::<T>() * self.capacity()
111    }
112    fn get_data_ptr(&self) -> Option<usize> {
113        Some(self.as_ptr() as usize)
114    }
115    fn get_data_size(&self) -> Option<usize> {
116        Some(std::mem::size_of::<T>() * self.len())
117    }
118}
119
120impl Trackable for String {
121    fn get_heap_ptr(&self) -> Option<usize> {
122        Some(self.as_ptr() as usize)
123    }
124    fn get_type_name(&self) -> &'static str {
125        "String"
126    }
127    fn get_size_estimate(&self) -> usize {
128        self.capacity()
129    }
130    fn get_data_ptr(&self) -> Option<usize> {
131        Some(self.as_ptr() as usize)
132    }
133    fn get_data_size(&self) -> Option<usize> {
134        Some(self.len())
135    }
136}
137
138impl<K, V> Trackable for std::collections::HashMap<K, V> {
139    fn get_heap_ptr(&self) -> Option<usize> {
140        None
141    }
142    fn get_type_name(&self) -> &'static str {
143        "HashMap<K, V>"
144    }
145    fn get_size_estimate(&self) -> usize {
146        std::mem::size_of::<(K, V)>() * self.capacity()
147    }
148    fn get_data_ptr(&self) -> Option<usize> {
149        None
150    }
151    fn get_data_size(&self) -> Option<usize> {
152        Some(std::mem::size_of::<(K, V)>() * self.len())
153    }
154}
155
156impl<K, V> Trackable for std::collections::BTreeMap<K, V> {
157    fn get_heap_ptr(&self) -> Option<usize> {
158        None
159    }
160    fn get_type_name(&self) -> &'static str {
161        "BTreeMap<K, V>"
162    }
163    fn get_size_estimate(&self) -> usize {
164        std::mem::size_of::<(K, V)>() * self.len()
165    }
166    fn get_data_ptr(&self) -> Option<usize> {
167        None
168    }
169    fn get_data_size(&self) -> Option<usize> {
170        Some(std::mem::size_of::<(K, V)>() * self.len())
171    }
172}
173
174impl<T> Trackable for std::collections::VecDeque<T> {
175    fn get_heap_ptr(&self) -> Option<usize> {
176        None
177    }
178    fn get_type_name(&self) -> &'static str {
179        "VecDeque<T>"
180    }
181    fn get_size_estimate(&self) -> usize {
182        std::mem::size_of::<T>() * self.capacity()
183    }
184    fn get_data_ptr(&self) -> Option<usize> {
185        None
186    }
187    fn get_data_size(&self) -> Option<usize> {
188        Some(std::mem::size_of::<T>() * self.len())
189    }
190}
191
192impl<T> Trackable for Box<T> {
193    fn get_heap_ptr(&self) -> Option<usize> {
194        Some(&**self as *const T as usize)
195    }
196    fn get_type_name(&self) -> &'static str {
197        "Box<T>"
198    }
199    fn get_size_estimate(&self) -> usize {
200        std::mem::size_of::<T>()
201    }
202    fn get_data_ptr(&self) -> Option<usize> {
203        Some(&**self as *const T as usize)
204    }
205    fn get_data_size(&self) -> Option<usize> {
206        Some(std::mem::size_of::<T>())
207    }
208}
209
210impl<T> Trackable for std::rc::Rc<T> {
211    fn get_heap_ptr(&self) -> Option<usize> {
212        Some(&**self as *const T as usize)
213    }
214    fn get_type_name(&self) -> &'static str {
215        "Rc<T>"
216    }
217    fn get_size_estimate(&self) -> usize {
218        std::mem::size_of::<T>()
219    }
220    fn get_ref_count(&self) -> Option<usize> {
221        Some(std::rc::Rc::strong_count(self))
222    }
223    fn get_data_ptr(&self) -> Option<usize> {
224        Some(&**self as *const T as usize)
225    }
226    fn get_data_size(&self) -> Option<usize> {
227        Some(std::mem::size_of::<T>())
228    }
229}
230
231impl<T> Trackable for std::sync::Arc<T> {
232    fn get_heap_ptr(&self) -> Option<usize> {
233        Some(&**self as *const T as usize)
234    }
235    fn get_type_name(&self) -> &'static str {
236        "Arc<T>"
237    }
238    fn get_size_estimate(&self) -> usize {
239        std::mem::size_of::<T>()
240    }
241    fn get_ref_count(&self) -> Option<usize> {
242        Some(std::sync::Arc::strong_count(self))
243    }
244    fn get_data_ptr(&self) -> Option<usize> {
245        Some(&**self as *const T as usize)
246    }
247    fn get_data_size(&self) -> Option<usize> {
248        Some(std::mem::size_of::<T>())
249    }
250}
251
252impl<T: Trackable> Trackable for std::cell::RefCell<T> {
253    fn get_heap_ptr(&self) -> Option<usize> {
254        None
255    }
256    fn get_type_name(&self) -> &'static str {
257        "RefCell<T>"
258    }
259    fn get_size_estimate(&self) -> usize {
260        std::mem::size_of::<T>()
261    }
262    fn get_data_ptr(&self) -> Option<usize> {
263        None
264    }
265    fn get_data_size(&self) -> Option<usize> {
266        Some(std::mem::size_of::<T>())
267    }
268}
269
270impl<T: Trackable> Trackable for std::sync::RwLock<T> {
271    fn get_heap_ptr(&self) -> Option<usize> {
272        None
273    }
274    fn get_type_name(&self) -> &'static str {
275        "RwLock<T>"
276    }
277    fn get_size_estimate(&self) -> usize {
278        std::mem::size_of::<T>()
279    }
280    fn get_data_ptr(&self) -> Option<usize> {
281        None
282    }
283    fn get_data_size(&self) -> Option<usize> {
284        Some(std::mem::size_of::<T>())
285    }
286}