memscope_rs/snapshot/
types.rs1use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
11pub struct ActiveAllocation {
12 pub ptr: usize,
14 pub size: usize,
16 pub allocated_at: u64,
18 pub var_name: Option<String>,
20 pub type_name: Option<String>,
22 pub thread_id: u64,
24 pub call_stack_hash: Option<u64>,
26}
27
28#[derive(Debug, Clone, Serialize, Deserialize, Default)]
30pub struct MemoryStats {
31 pub total_allocations: usize,
33 pub total_reallocations: usize,
35 pub total_deallocations: usize,
37 pub unmatched_deallocations: usize,
39 pub active_allocations: usize,
41 pub total_allocated: usize,
43 pub total_deallocated: usize,
45 pub current_memory: usize,
47 pub peak_memory: usize,
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize, Default)]
53pub struct ThreadMemoryStats {
54 pub thread_id: u64,
56 pub allocation_count: usize,
58 pub total_allocated: usize,
60 pub total_deallocated: usize,
62 pub current_memory: usize,
64 pub peak_memory: usize,
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize, Default)]
70pub struct MemorySnapshot {
71 pub timestamp: u64,
73 pub stats: MemoryStats,
75 pub active_allocations: HashMap<usize, ActiveAllocation>,
77 pub thread_stats: HashMap<u64, ThreadMemoryStats>,
79}
80
81impl MemorySnapshot {
82 pub fn new() -> Self {
84 Self {
85 timestamp: std::time::SystemTime::now()
86 .duration_since(std::time::UNIX_EPOCH)
87 .unwrap_or_default()
88 .as_nanos() as u64,
89 stats: MemoryStats::default(),
90 active_allocations: HashMap::new(),
91 thread_stats: HashMap::new(),
92 }
93 }
94
95 pub fn from_allocation_infos(
97 allocations: Vec<crate::capture::backends::core_types::AllocationInfo>,
98 ) -> Self {
99 let mut snapshot = Self::new();
100 let mut thread_stats: HashMap<u64, ThreadMemoryStats> = HashMap::new();
101 let mut current_memory: usize = 0;
102
103 for alloc in allocations {
104 let thread_id = alloc.thread_id;
105
106 let active_alloc = ActiveAllocation {
107 ptr: alloc.ptr,
108 size: alloc.size,
109 allocated_at: alloc.allocated_at_ns,
110 var_name: alloc.var_name,
111 type_name: alloc.type_name,
112 thread_id,
113 call_stack_hash: None,
114 };
115
116 current_memory += alloc.size;
117
118 snapshot.stats.total_allocations += 1;
119 snapshot.stats.total_allocated += alloc.size;
120
121 let thread_stat = thread_stats
122 .entry(thread_id)
123 .or_insert_with(|| ThreadMemoryStats {
124 thread_id,
125 allocation_count: 0,
126 total_allocated: 0,
127 total_deallocated: 0,
128 current_memory: 0,
129 peak_memory: 0,
130 });
131
132 thread_stat.allocation_count += 1;
133 thread_stat.total_allocated += alloc.size;
134 thread_stat.current_memory += alloc.size;
135 if thread_stat.current_memory > thread_stat.peak_memory {
136 thread_stat.peak_memory = thread_stat.current_memory;
137 }
138
139 snapshot.active_allocations.insert(alloc.ptr, active_alloc);
140 }
141
142 snapshot.stats.current_memory = current_memory;
143 snapshot.stats.peak_memory = 0; snapshot.stats.active_allocations = snapshot.active_allocations.len();
145 snapshot.thread_stats = thread_stats;
146
147 snapshot
148 }
149
150 pub fn active_count(&self) -> usize {
152 self.active_allocations.len()
153 }
154
155 pub fn current_memory(&self) -> usize {
157 self.stats.current_memory
158 }
159
160 pub fn peak_memory(&self) -> usize {
162 self.stats.peak_memory
163 }
164}