use super::LpgStore;
use grafeo_common::memory::usage::{IndexMemory, MvccMemory, StoreMemory, StringPoolMemory};
use std::mem::size_of;
impl LpgStore {
#[must_use]
pub fn memory_breakdown(&self) -> (StoreMemory, IndexMemory, MvccMemory, StringPoolMemory) {
let store = self.store_memory();
let (mvcc, _) = self.mvcc_memory();
let indexes = self.index_memory();
let string_pool = self.string_pool_memory();
(store, indexes, mvcc, string_pool)
}
fn store_memory(&self) -> StoreMemory {
let node_props_bytes = self.node_properties.heap_memory_bytes();
let edge_props_bytes = self.edge_properties.heap_memory_bytes();
let col_count = self.node_properties.column_count() + self.edge_properties.column_count();
#[cfg(not(feature = "tiered-storage"))]
let (nodes_bytes, edges_bytes) = {
let nodes = self.nodes.read();
let edges = self.edges.read();
let n = nodes.capacity()
* (size_of::<grafeo_common::types::NodeId>()
+ size_of::<grafeo_common::mvcc::VersionChain<super::super::NodeRecord>>()
+ 1);
let e = edges.capacity()
* (size_of::<grafeo_common::types::EdgeId>()
+ size_of::<grafeo_common::mvcc::VersionChain<super::super::EdgeRecord>>()
+ 1);
(n, e)
};
#[cfg(feature = "tiered-storage")]
let (nodes_bytes, edges_bytes) = {
let nv = self.node_versions.read();
let ev = self.edge_versions.read();
let n = nv.capacity()
* (size_of::<grafeo_common::types::NodeId>()
+ size_of::<grafeo_common::mvcc::VersionIndex>()
+ 1);
let e = ev.capacity()
* (size_of::<grafeo_common::types::EdgeId>()
+ size_of::<grafeo_common::mvcc::VersionIndex>()
+ 1);
(n, e)
};
let mut store = StoreMemory {
nodes_bytes,
edges_bytes,
node_properties_bytes: node_props_bytes,
edge_properties_bytes: edge_props_bytes,
property_column_count: col_count,
..Default::default()
};
store.compute_total();
store
}
fn mvcc_memory(&self) -> (MvccMemory, usize) {
#[cfg(not(feature = "tiered-storage"))]
{
let nodes = self.nodes.read();
let edges = self.edges.read();
let mut node_chain_bytes = 0usize;
let mut edge_chain_bytes = 0usize;
let mut total_depth = 0usize;
let mut max_depth = 0usize;
let total_chains = nodes.len() + edges.len();
for chain in nodes.values() {
let depth = chain.version_count();
node_chain_bytes += chain.heap_memory_bytes();
total_depth += depth;
if depth > max_depth {
max_depth = depth;
}
}
for chain in edges.values() {
let depth = chain.version_count();
edge_chain_bytes += chain.heap_memory_bytes();
total_depth += depth;
if depth > max_depth {
max_depth = depth;
}
}
let average_chain_depth = if total_chains > 0 {
total_depth as f64 / total_chains as f64
} else {
0.0
};
let mut mvcc = MvccMemory {
node_version_chains_bytes: node_chain_bytes,
edge_version_chains_bytes: edge_chain_bytes,
average_chain_depth,
max_chain_depth: max_depth,
..Default::default()
};
mvcc.compute_total();
(mvcc, 0)
}
#[cfg(feature = "tiered-storage")]
{
let nv = self.node_versions.read();
let ev = self.edge_versions.read();
let node_count = nv.len();
let edge_count = ev.len();
let node_chain_bytes = node_count * 64;
let edge_chain_bytes = edge_count * 64;
let total_chains = node_count + edge_count;
let mvcc = MvccMemory {
node_version_chains_bytes: node_chain_bytes,
edge_version_chains_bytes: edge_chain_bytes,
average_chain_depth: if total_chains > 0 { 1.0 } else { 0.0 },
max_chain_depth: usize::from(total_chains > 0),
total_bytes: node_chain_bytes + edge_chain_bytes,
};
(mvcc, 0)
}
}
fn index_memory(&self) -> IndexMemory {
let forward_bytes = self.forward_adj.heap_memory_bytes();
let backward_bytes = self
.backward_adj
.as_ref()
.map_or(0, |adj| adj.heap_memory_bytes());
let label_idx = self.label_index.read();
let label_index_bytes: usize = label_idx
.iter()
.map(|map| map.capacity() * (size_of::<grafeo_common::types::NodeId>() + 1))
.sum::<usize>()
+ label_idx.capacity()
* size_of::<grafeo_common::utils::hash::FxHashMap<grafeo_common::types::NodeId, ()>>(
);
drop(label_idx);
let node_labels = self.node_labels.read();
#[cfg(not(feature = "temporal"))]
let node_labels_bytes = node_labels.capacity()
* (size_of::<grafeo_common::types::NodeId>()
+ size_of::<grafeo_common::utils::hash::FxHashSet<u32>>()
+ 1)
+ node_labels
.values()
.map(|set| set.capacity() * (size_of::<u32>() + 1))
.sum::<usize>();
#[cfg(feature = "temporal")]
let node_labels_bytes = node_labels.capacity()
* (size_of::<grafeo_common::types::NodeId>()
+ size_of::<
grafeo_common::temporal::VersionLog<grafeo_common::utils::hash::FxHashSet<u32>>,
>()
+ 1)
+ node_labels
.values()
.map(|log| log.len() * size_of::<grafeo_common::utils::hash::FxHashSet<u32>>())
.sum::<usize>();
drop(node_labels);
let prop_indexes = self.property_indexes.read();
let property_index_bytes: usize = prop_indexes
.values()
.map(|dmap| {
dmap.len()
* (size_of::<grafeo_common::types::HashableValue>()
+ size_of::<
grafeo_common::utils::hash::FxHashSet<grafeo_common::types::NodeId>,
>()
+ 32)
})
.sum();
drop(prop_indexes);
#[cfg(feature = "vector-index")]
let vector_indexes: Vec<grafeo_common::memory::NamedMemory> = {
use grafeo_common::memory::NamedMemory;
let vidx = self.vector_indexes.read();
vidx.iter()
.map(|(name, idx)| NamedMemory {
name: name.clone(),
bytes: idx.heap_memory_bytes(),
item_count: idx.len(),
})
.collect()
};
#[cfg(not(feature = "vector-index"))]
let vector_indexes = Vec::new();
#[cfg(feature = "text-index")]
let text_indexes: Vec<grafeo_common::memory::NamedMemory> = {
use grafeo_common::memory::NamedMemory;
let tidx = self.text_indexes.read();
tidx.iter()
.map(|(name, idx)| {
let guard = idx.read();
NamedMemory {
name: name.clone(),
bytes: guard.heap_memory_bytes(),
item_count: guard.len(),
}
})
.collect()
};
#[cfg(not(feature = "text-index"))]
let text_indexes = Vec::new();
let mut indexes = IndexMemory {
forward_adjacency_bytes: forward_bytes,
backward_adjacency_bytes: backward_bytes,
label_index_bytes,
node_labels_bytes,
property_index_bytes,
vector_indexes,
text_indexes,
..Default::default()
};
indexes.compute_total();
indexes
}
fn string_pool_memory(&self) -> StringPoolMemory {
let labels_to_id = self.label_to_id.read();
let id_to_label = self.id_to_label.read();
let edge_type_to_id = self.edge_type_to_id.read();
let id_to_edge_type = self.id_to_edge_type.read();
let label_count = id_to_label.len();
let edge_type_count = id_to_edge_type.len();
let label_map_bytes = labels_to_id.capacity()
* (size_of::<arcstr::ArcStr>() + size_of::<u32>() + 1)
+ labels_to_id.keys().map(|s| s.len()).sum::<usize>();
let label_vec_bytes = id_to_label.capacity() * size_of::<arcstr::ArcStr>()
+ id_to_label.iter().map(|s| s.len()).sum::<usize>();
let label_registry_bytes = label_map_bytes + label_vec_bytes;
let et_map_bytes = edge_type_to_id.capacity()
* (size_of::<arcstr::ArcStr>() + size_of::<u32>() + 1)
+ edge_type_to_id.keys().map(|s| s.len()).sum::<usize>();
let et_vec_bytes = id_to_edge_type.capacity() * size_of::<arcstr::ArcStr>()
+ id_to_edge_type.iter().map(|s| s.len()).sum::<usize>();
let edge_type_registry_bytes = et_map_bytes + et_vec_bytes;
let mut sp = StringPoolMemory {
label_registry_bytes,
edge_type_registry_bytes,
label_count,
edge_type_count,
..Default::default()
};
sp.compute_total();
sp
}
}