memscope_rs/timeline/
query.rs1use crate::event_store::event::{MemoryEvent, MemoryEventType};
7use crate::event_store::EventStore;
8use std::sync::Arc;
9
10pub struct TimelineQuery {
15 event_store: Arc<EventStore>,
17}
18
19impl TimelineQuery {
20 pub fn new(event_store: Arc<EventStore>) -> Self {
22 Self { event_store }
23 }
24
25 pub fn get_events_in_range(&self, start: u64, end: u64) -> Vec<MemoryEvent> {
31 self.event_store
32 .snapshot()
33 .into_iter()
34 .filter(|e| e.timestamp >= start && e.timestamp < end)
35 .collect()
36 }
37
38 pub fn get_allocations_in_range(&self, start: u64, end: u64) -> Vec<MemoryEvent> {
44 self.get_events_in_range(start, end)
45 .into_iter()
46 .filter(|e| e.event_type == MemoryEventType::Allocate)
47 .collect()
48 }
49
50 pub fn get_deallocations_in_range(&self, start: u64, end: u64) -> Vec<MemoryEvent> {
56 self.get_events_in_range(start, end)
57 .into_iter()
58 .filter(|e| e.event_type == MemoryEventType::Deallocate)
59 .collect()
60 }
61
62 pub fn get_thread_events_in_range(
69 &self,
70 thread_id: u64,
71 start: u64,
72 end: u64,
73 ) -> Vec<MemoryEvent> {
74 self.get_events_in_range(start, end)
75 .into_iter()
76 .filter(|e| e.thread_id == thread_id)
77 .collect()
78 }
79
80 pub fn get_memory_usage_over_time(
91 &self,
92 start: u64,
93 end: u64,
94 interval_ms: u64,
95 ) -> Vec<(u64, usize)> {
96 let mut result = Vec::new();
97 let interval_ns = interval_ms * 1_000_000;
98
99 let mut all_events: Vec<(u64, MemoryEvent)> = Vec::new();
101
102 for event in self.get_events_in_range(start, end) {
103 all_events.push((event.timestamp, event));
104 }
105
106 all_events.sort_by_key(|(ts, _)| *ts);
108
109 let mut current = start;
111 let mut event_idx = 0;
112 let mut running_memory: usize = 0;
113
114 while current < end {
115 while event_idx < all_events.len() {
117 let (ts, event) = &all_events[event_idx];
118 if *ts > current {
119 break;
120 }
121
122 match &event.event_type {
123 MemoryEventType::Allocate => {
124 running_memory += event.size;
125 }
126 MemoryEventType::Deallocate => {
127 running_memory = running_memory.saturating_sub(event.size);
128 }
129 MemoryEventType::Reallocate => {
130 let old_size = event.old_size.unwrap_or(0);
131 running_memory = running_memory
132 .saturating_sub(old_size)
133 .saturating_add(event.size);
134 }
135 _ => {}
136 }
137
138 event_idx += 1;
139 }
140
141 result.push((current, running_memory));
142 current += interval_ns;
143 }
144
145 result
146 }
147
148 pub fn get_peak_memory_in_range(&self, start: u64, end: u64) -> usize {
158 let mut all_events: Vec<MemoryEvent> = Vec::new();
160
161 for event in self.get_events_in_range(start, end) {
162 all_events.push(event);
163 }
164
165 all_events.sort_by_key(|e| e.timestamp);
166
167 let mut running_memory: usize = 0;
169 let mut peak_memory: usize = 0;
170
171 for event in all_events {
172 match &event.event_type {
173 MemoryEventType::Allocate => {
174 running_memory += event.size;
175 }
176 MemoryEventType::Deallocate => {
177 running_memory = running_memory.saturating_sub(event.size);
178 }
179 MemoryEventType::Reallocate => {
180 let old_size = event.old_size.unwrap_or(0);
181 running_memory = running_memory
182 .saturating_sub(old_size)
183 .saturating_add(event.size);
184 }
185 _ => {}
186 }
187 peak_memory = peak_memory.max(running_memory);
188 }
189
190 peak_memory
191 }
192
193 pub fn get_event_rate(&self, start: u64, end: u64) -> f64 {
199 let events = self.get_events_in_range(start, end);
200 let duration_ns = end.saturating_sub(start) as f64;
201 if duration_ns > 0.0 {
202 (events.len() as f64) / (duration_ns / 1_000_000_000.0)
203 } else {
204 0.0
205 }
206 }
207}
208
209#[cfg(test)]
210mod tests {
211 use super::*;
212
213 #[test]
214 fn test_timeline_query_creation() {
215 let event_store = Arc::new(EventStore::new());
216 let query = TimelineQuery::new(event_store);
217 let events = query.get_events_in_range(0, 1000);
218 assert!(events.is_empty());
219 }
220
221 #[test]
222 fn test_get_events_in_range() {
223 let event_store = Arc::new(EventStore::new());
224 let event1 = MemoryEvent::allocate(0x1000, 1024, 123);
225 event_store.record(event1);
226 let event2 = MemoryEvent::deallocate(0x1000, 1024, 456);
227 event_store.record(event2);
228
229 let query = TimelineQuery::new(event_store);
230 let events = query.get_events_in_range(0, u64::MAX);
232 assert_eq!(events.len(), 2);
233 }
234
235 #[test]
236 fn test_memory_usage_over_time() {
237 let event_store = Arc::new(EventStore::new());
238 let event = MemoryEvent::allocate(0x1000, 1024, 123);
239 event_store.record(event);
240
241 let query = TimelineQuery::new(event_store);
242 let usage = query.get_memory_usage_over_time(0, 1000, 100);
243 assert!(!usage.is_empty());
244 }
245}