pub use grafeo_common::memory::usage::{
IndexMemory, MvccMemory, NamedMemory, StoreMemory, StringPoolMemory,
};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct MemoryUsage {
pub total_bytes: usize,
pub store: StoreMemory,
pub indexes: IndexMemory,
pub mvcc: MvccMemory,
pub caches: CacheMemory,
pub string_pool: StringPoolMemory,
pub buffer_manager: BufferManagerMemory,
#[serde(default, skip_serializing_if = "RdfMemory::is_empty")]
pub rdf: RdfMemory,
#[serde(default, skip_serializing_if = "CdcMemory::is_empty")]
pub cdc: CdcMemory,
}
impl MemoryUsage {
pub fn compute_total(&mut self) {
self.total_bytes = self.store.total_bytes
+ self.indexes.total_bytes
+ self.mvcc.total_bytes
+ self.caches.total_bytes
+ self.string_pool.total_bytes
+ self.buffer_manager.allocated_bytes
+ self.rdf.total_bytes
+ self.cdc.total_bytes;
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct CacheMemory {
pub total_bytes: usize,
pub parsed_plan_cache_bytes: usize,
pub optimized_plan_cache_bytes: usize,
pub cached_plan_count: usize,
}
impl CacheMemory {
pub fn compute_total(&mut self) {
self.total_bytes = self.parsed_plan_cache_bytes + self.optimized_plan_cache_bytes;
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct RdfMemory {
pub total_bytes: usize,
pub triple_count: usize,
pub triples_and_indexes_bytes: usize,
pub term_dictionary_bytes: usize,
pub ring_index_bytes: usize,
pub named_graph_count: usize,
}
impl RdfMemory {
#[must_use]
pub fn is_empty(&self) -> bool {
self.total_bytes == 0 && self.triple_count == 0
}
pub fn compute_total(&mut self) {
self.total_bytes =
self.triples_and_indexes_bytes + self.term_dictionary_bytes + self.ring_index_bytes;
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct CdcMemory {
pub total_bytes: usize,
pub entity_count: usize,
pub event_count: usize,
}
impl CdcMemory {
#[must_use]
pub fn is_empty(&self) -> bool {
self.event_count == 0 && self.total_bytes == 0
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct BufferManagerMemory {
pub budget_bytes: usize,
pub allocated_bytes: usize,
pub graph_storage_bytes: usize,
pub index_buffers_bytes: usize,
pub execution_buffers_bytes: usize,
pub spill_staging_bytes: usize,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_memory_usage_is_zero() {
let usage = MemoryUsage::default();
assert_eq!(usage.total_bytes, 0);
assert_eq!(usage.store.total_bytes, 0);
assert_eq!(usage.indexes.total_bytes, 0);
assert_eq!(usage.mvcc.total_bytes, 0);
assert_eq!(usage.caches.total_bytes, 0);
assert_eq!(usage.string_pool.total_bytes, 0);
assert_eq!(usage.buffer_manager.allocated_bytes, 0);
}
#[test]
fn compute_total_sums_children() {
let mut usage = MemoryUsage {
store: StoreMemory {
total_bytes: 100,
..Default::default()
},
indexes: IndexMemory {
total_bytes: 200,
..Default::default()
},
mvcc: MvccMemory {
total_bytes: 50,
..Default::default()
},
caches: CacheMemory {
total_bytes: 30,
..Default::default()
},
string_pool: StringPoolMemory {
total_bytes: 10,
..Default::default()
},
buffer_manager: BufferManagerMemory {
allocated_bytes: 20,
..Default::default()
},
rdf: RdfMemory {
total_bytes: 500,
triple_count: 10,
triples_and_indexes_bytes: 500,
..Default::default()
},
cdc: CdcMemory {
total_bytes: 40,
event_count: 3,
entity_count: 2,
},
..Default::default()
};
usage.compute_total();
assert_eq!(usage.total_bytes, 950);
}
#[test]
fn rdf_and_cdc_default_is_empty() {
let rdf = RdfMemory::default();
assert!(rdf.is_empty());
let cdc = CdcMemory::default();
assert!(cdc.is_empty());
}
#[test]
fn rdf_compute_total_sums_children() {
let mut rdf = RdfMemory {
triples_and_indexes_bytes: 100,
term_dictionary_bytes: 50,
ring_index_bytes: 25,
..Default::default()
};
rdf.compute_total();
assert_eq!(rdf.total_bytes, 175);
}
#[test]
fn serde_roundtrip() {
let mut usage = MemoryUsage::default();
usage.store.nodes_bytes = 1024;
usage.indexes.vector_indexes.push(NamedMemory {
name: "vec_idx".to_string(),
bytes: 512,
item_count: 100,
});
usage.mvcc.average_chain_depth = 1.5;
let json = serde_json::to_string(&usage).unwrap();
let deserialized: MemoryUsage = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized.store.nodes_bytes, 1024);
assert_eq!(deserialized.indexes.vector_indexes.len(), 1);
assert_eq!(deserialized.indexes.vector_indexes[0].name, "vec_idx");
assert!((deserialized.mvcc.average_chain_depth - 1.5).abs() < f64::EPSILON);
}
}