sorting_race/services/
memory.rs1use crate::models::traits::MemoryTracker;
4
5#[derive(Debug, Default)]
7pub struct StandardMemoryTracker {
8 current: usize,
9 peak: usize,
10}
11
12impl StandardMemoryTracker {
13 pub fn new() -> Self {
15 Self::default()
16 }
17}
18
19impl MemoryTracker for StandardMemoryTracker {
20 fn alloc(&mut self, bytes: usize) {
21 self.current = self.current.saturating_add(bytes);
23 self.peak = self.peak.max(self.current);
24 }
25
26 fn free(&mut self, bytes: usize) {
27 self.current = self.current.saturating_sub(bytes);
28 }
29
30 fn current(&self) -> usize {
31 self.current
32 }
33
34 fn peak(&self) -> usize {
35 self.peak
36 }
37
38 fn reset(&mut self) {
39 self.current = 0;
40 self.peak = 0;
41 }
42}
43
44#[derive(Debug, Default)]
46pub struct VerboseMemoryTracker {
47 current: usize,
48 peak: usize,
49 operations: Vec<MemoryOperation>,
50}
51
52#[derive(Debug, Clone)]
53pub struct MemoryOperation {
54 pub op_type: MemoryOpType,
55 pub bytes: usize,
56 pub current_after: usize,
57 pub peak_after: usize,
58}
59
60#[derive(Debug, Clone, PartialEq)]
61pub enum MemoryOpType {
62 Alloc,
63 Free,
64 Reset,
65}
66
67impl VerboseMemoryTracker {
68 pub fn new() -> Self {
70 Self::default()
71 }
72
73 pub fn get_operations(&self) -> &[MemoryOperation] {
75 &self.operations
76 }
77
78 pub fn clear_log(&mut self) {
80 self.operations.clear();
81 }
82
83 fn log_operation(&mut self, op_type: MemoryOpType, bytes: usize) {
84 self.operations.push(MemoryOperation {
85 op_type,
86 bytes,
87 current_after: self.current,
88 peak_after: self.peak,
89 });
90 }
91}
92
93impl MemoryTracker for VerboseMemoryTracker {
94 fn alloc(&mut self, bytes: usize) {
95 self.current = self.current.saturating_add(bytes);
96 self.peak = self.peak.max(self.current);
97 self.log_operation(MemoryOpType::Alloc, bytes);
98 }
99
100 fn free(&mut self, bytes: usize) {
101 self.current = self.current.saturating_sub(bytes);
102 self.log_operation(MemoryOpType::Free, bytes);
103 }
104
105 fn current(&self) -> usize {
106 self.current
107 }
108
109 fn peak(&self) -> usize {
110 self.peak
111 }
112
113 fn reset(&mut self) {
114 self.current = 0;
115 self.peak = 0;
116 self.log_operation(MemoryOpType::Reset, 0);
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123
124 #[test]
125 fn test_standard_memory_tracker() {
126 let mut tracker = StandardMemoryTracker::new();
127
128 assert_eq!(tracker.current(), 0);
129 assert_eq!(tracker.peak(), 0);
130
131 tracker.alloc(100);
132 assert_eq!(tracker.current(), 100);
133 assert_eq!(tracker.peak(), 100);
134
135 tracker.free(50);
136 assert_eq!(tracker.current(), 50);
137 assert_eq!(tracker.peak(), 100);
138
139 tracker.reset();
140 assert_eq!(tracker.current(), 0);
141 assert_eq!(tracker.peak(), 0);
142 }
143
144 #[test]
145 fn test_verbose_memory_tracker() {
146 let mut tracker = VerboseMemoryTracker::new();
147
148 tracker.alloc(100);
149 tracker.free(50);
150 tracker.reset();
151
152 let ops = tracker.get_operations();
153 assert_eq!(ops.len(), 3);
154
155 assert_eq!(ops[0].op_type, MemoryOpType::Alloc);
156 assert_eq!(ops[1].op_type, MemoryOpType::Free);
157 assert_eq!(ops[2].op_type, MemoryOpType::Reset);
158 }
159}