qudag_protocol/
instrumentation.rs1use std::sync::atomic::{AtomicUsize, Ordering};
2use std::time::Instant;
3
4pub struct MemoryTracker {
6 peak_usage: AtomicUsize,
7 allocation_count: AtomicUsize,
8 deallocation_count: AtomicUsize,
9 start_time: Instant,
10}
11
12impl Default for MemoryTracker {
13 fn default() -> Self {
14 Self::new()
15 }
16}
17
18impl MemoryTracker {
19 pub fn new() -> Self {
20 Self {
21 peak_usage: AtomicUsize::new(0),
22 allocation_count: AtomicUsize::new(0),
23 deallocation_count: AtomicUsize::new(0),
24 start_time: Instant::now(),
25 }
26 }
27
28 pub fn track_allocation(&self, _size: usize) {
29 self.allocation_count.fetch_add(1, Ordering::SeqCst);
30 let current = super::allocator::get_memory_usage();
31 let mut peak = self.peak_usage.load(Ordering::SeqCst);
32 while current > peak {
33 match self.peak_usage.compare_exchange(
34 peak,
35 current,
36 Ordering::SeqCst,
37 Ordering::SeqCst,
38 ) {
39 Ok(_) => break,
40 Err(x) => peak = x,
41 }
42 }
43 }
44
45 pub fn track_deallocation(&self, _size: usize) {
46 self.deallocation_count.fetch_add(1, Ordering::SeqCst);
47 }
48
49 pub fn get_metrics(&self) -> MemoryMetrics {
50 MemoryMetrics {
51 current_usage: super::allocator::get_memory_usage(),
52 peak_usage: self.peak_usage.load(Ordering::SeqCst),
53 allocation_count: self.allocation_count.load(Ordering::SeqCst),
54 deallocation_count: self.deallocation_count.load(Ordering::SeqCst),
55 total_allocated: super::allocator::get_total_allocated(),
56 total_deallocated: super::allocator::get_total_deallocated(),
57 uptime_seconds: self.start_time.elapsed().as_secs(),
58 }
59 }
60}
61
62#[derive(Debug, Clone, Copy)]
64pub struct MemoryMetrics {
65 pub current_usage: usize,
66 pub peak_usage: usize,
67 pub allocation_count: usize,
68 pub deallocation_count: usize,
69 pub total_allocated: usize,
70 pub total_deallocated: usize,
71 pub uptime_seconds: u64,
72}
73
74impl MemoryMetrics {
75 pub fn allocation_rate(&self) -> f64 {
76 self.allocation_count as f64 / self.uptime_seconds as f64
77 }
78
79 pub fn deallocation_rate(&self) -> f64 {
80 self.deallocation_count as f64 / self.uptime_seconds as f64
81 }
82
83 pub fn churn_rate(&self) -> f64 {
84 (self.total_allocated + self.total_deallocated) as f64 / self.uptime_seconds as f64
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91 use std::thread;
92 use std::time::Duration;
93
94 #[test]
95 fn test_memory_tracking() {
96 let tracker = MemoryTracker::new();
97
98 tracker.track_allocation(1024);
100 tracker.track_allocation(2048);
101
102 tracker.track_deallocation(1024);
104
105 thread::sleep(Duration::from_secs(1));
107
108 let metrics = tracker.get_metrics();
109
110 assert_eq!(metrics.allocation_count, 2);
111 assert_eq!(metrics.deallocation_count, 1);
112 assert!(metrics.uptime_seconds >= 1);
113 assert!(metrics.allocation_rate() > 0.0);
114 assert!(metrics.deallocation_rate() > 0.0);
115 assert!(metrics.churn_rate() > 0.0);
116 }
117}