1pub use grafeo_common::memory::usage::{
8 IndexMemory, MvccMemory, NamedMemory, StoreMemory, StringPoolMemory,
9};
10use serde::{Deserialize, Serialize};
11
12#[derive(Debug, Clone, Default, Serialize, Deserialize)]
14pub struct MemoryUsage {
15 pub total_bytes: usize,
17 pub store: StoreMemory,
19 pub indexes: IndexMemory,
21 pub mvcc: MvccMemory,
23 pub caches: CacheMemory,
25 pub string_pool: StringPoolMemory,
27 pub buffer_manager: BufferManagerMemory,
29 #[serde(default, skip_serializing_if = "RdfMemory::is_empty")]
31 pub rdf: RdfMemory,
32 #[serde(default, skip_serializing_if = "CdcMemory::is_empty")]
34 pub cdc: CdcMemory,
35}
36
37impl MemoryUsage {
38 pub fn compute_total(&mut self) {
40 self.total_bytes = self.store.total_bytes
41 + self.indexes.total_bytes
42 + self.mvcc.total_bytes
43 + self.caches.total_bytes
44 + self.string_pool.total_bytes
45 + self.buffer_manager.allocated_bytes
46 + self.rdf.total_bytes
47 + self.cdc.total_bytes;
48 }
49}
50
51#[derive(Debug, Clone, Default, Serialize, Deserialize)]
53pub struct CacheMemory {
54 pub total_bytes: usize,
56 pub parsed_plan_cache_bytes: usize,
58 pub optimized_plan_cache_bytes: usize,
60 pub cached_plan_count: usize,
62}
63
64impl CacheMemory {
65 pub fn compute_total(&mut self) {
67 self.total_bytes = self.parsed_plan_cache_bytes + self.optimized_plan_cache_bytes;
68 }
69}
70
71#[derive(Debug, Clone, Default, Serialize, Deserialize)]
76pub struct RdfMemory {
77 pub total_bytes: usize,
79 pub triple_count: usize,
81 pub triples_and_indexes_bytes: usize,
83 pub term_dictionary_bytes: usize,
85 pub ring_index_bytes: usize,
87 pub named_graph_count: usize,
90}
91
92impl RdfMemory {
93 #[must_use]
96 pub fn is_empty(&self) -> bool {
97 self.total_bytes == 0 && self.triple_count == 0
98 }
99
100 pub fn compute_total(&mut self) {
102 self.total_bytes =
103 self.triples_and_indexes_bytes + self.term_dictionary_bytes + self.ring_index_bytes;
104 }
105}
106
107#[derive(Debug, Clone, Default, Serialize, Deserialize)]
111pub struct CdcMemory {
112 pub total_bytes: usize,
114 pub entity_count: usize,
116 pub event_count: usize,
118}
119
120impl CdcMemory {
121 #[must_use]
123 pub fn is_empty(&self) -> bool {
124 self.event_count == 0 && self.total_bytes == 0
125 }
126}
127
128#[derive(Debug, Clone, Default, Serialize, Deserialize)]
130pub struct BufferManagerMemory {
131 pub budget_bytes: usize,
133 pub allocated_bytes: usize,
135 pub graph_storage_bytes: usize,
137 pub index_buffers_bytes: usize,
139 pub execution_buffers_bytes: usize,
141 pub spill_staging_bytes: usize,
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148
149 #[test]
150 fn default_memory_usage_is_zero() {
151 let usage = MemoryUsage::default();
152 assert_eq!(usage.total_bytes, 0);
153 assert_eq!(usage.store.total_bytes, 0);
154 assert_eq!(usage.indexes.total_bytes, 0);
155 assert_eq!(usage.mvcc.total_bytes, 0);
156 assert_eq!(usage.caches.total_bytes, 0);
157 assert_eq!(usage.string_pool.total_bytes, 0);
158 assert_eq!(usage.buffer_manager.allocated_bytes, 0);
159 }
160
161 #[test]
162 fn compute_total_sums_children() {
163 let mut usage = MemoryUsage {
164 store: StoreMemory {
165 total_bytes: 100,
166 ..Default::default()
167 },
168 indexes: IndexMemory {
169 total_bytes: 200,
170 ..Default::default()
171 },
172 mvcc: MvccMemory {
173 total_bytes: 50,
174 ..Default::default()
175 },
176 caches: CacheMemory {
177 total_bytes: 30,
178 ..Default::default()
179 },
180 string_pool: StringPoolMemory {
181 total_bytes: 10,
182 ..Default::default()
183 },
184 buffer_manager: BufferManagerMemory {
185 allocated_bytes: 20,
186 ..Default::default()
187 },
188 rdf: RdfMemory {
189 total_bytes: 500,
190 triple_count: 10,
191 triples_and_indexes_bytes: 500,
192 ..Default::default()
193 },
194 cdc: CdcMemory {
195 total_bytes: 40,
196 event_count: 3,
197 entity_count: 2,
198 },
199 ..Default::default()
200 };
201 usage.compute_total();
202 assert_eq!(usage.total_bytes, 950);
203 }
204
205 #[test]
206 fn rdf_and_cdc_default_is_empty() {
207 let rdf = RdfMemory::default();
208 assert!(rdf.is_empty());
209 let cdc = CdcMemory::default();
210 assert!(cdc.is_empty());
211 }
212
213 #[test]
214 fn rdf_compute_total_sums_children() {
215 let mut rdf = RdfMemory {
216 triples_and_indexes_bytes: 100,
217 term_dictionary_bytes: 50,
218 ring_index_bytes: 25,
219 ..Default::default()
220 };
221 rdf.compute_total();
222 assert_eq!(rdf.total_bytes, 175);
223 }
224
225 #[test]
226 fn serde_roundtrip() {
227 let mut usage = MemoryUsage::default();
228 usage.store.nodes_bytes = 1024;
229 usage.indexes.vector_indexes.push(NamedMemory {
230 name: "vec_idx".to_string(),
231 bytes: 512,
232 item_count: 100,
233 });
234 usage.mvcc.average_chain_depth = 1.5;
235
236 let json = serde_json::to_string(&usage).unwrap();
237 let deserialized: MemoryUsage = serde_json::from_str(&json).unwrap();
238
239 assert_eq!(deserialized.store.nodes_bytes, 1024);
240 assert_eq!(deserialized.indexes.vector_indexes.len(), 1);
241 assert_eq!(deserialized.indexes.vector_indexes[0].name, "vec_idx");
242 assert!((deserialized.mvcc.average_chain_depth - 1.5).abs() < f64::EPSILON);
243 }
244}