use super::super::{ColdStamps, HotNbr};
use super::MutableCsr;
use crate::edge::FragmentationStats;
impl MutableCsr {
pub fn overflow_chunk_allocs(&self) -> u64 {
self.overflow_chunk_allocs
}
pub fn primary_block_allocs(&self) -> u64 {
self.primary_block_allocs
}
pub fn repack_count(&self) -> u64 {
self.repack_count
}
pub fn tombstone_reuse_count(&self) -> u64 {
self.tombstone_reuse_count
}
pub fn tombstone_reuse_hint_hits(&self) -> u64 {
self.tombstone_reuse_hint_hits
}
pub fn tombstone_reuse_hint_misses(&self) -> u64 {
self.tombstone_reuse_hint_misses
}
pub fn tombstone_reuse_hint_hit_rate(&self) -> f32 {
let hits = self.tombstone_reuse_hint_hits as f64;
let misses = self.tombstone_reuse_hint_misses as f64;
if hits + misses == 0.0 {
0.0
} else {
(hits / (hits + misses)) as f32
}
}
pub fn live_set_rebuild_count(&self) -> u64 {
self.live_set_rebuild_count
}
pub fn reset_baseline_counters(&mut self) {
self.overflow_chunk_allocs = 0;
self.primary_block_allocs = 0;
self.repack_count = 0;
self.tombstone_reuse_count = 0;
self.live_set_rebuild_count = 0;
self.tombstone_reuse_hint_hits = 0;
self.tombstone_reuse_hint_misses = 0;
}
}
impl MutableCsr {
pub fn used_memory_size(&self) -> usize {
let slot_bytes = std::mem::size_of::<HotNbr>() + std::mem::size_of::<ColdStamps>();
let arrays = self.hot_list.capacity() * std::mem::size_of::<HotNbr>()
+ self.cold_list.capacity() * std::mem::size_of::<ColdStamps>()
+ self.rows.adj_offsets.capacity() * std::mem::size_of::<u32>()
+ self.rows.degrees.capacity() * std::mem::size_of::<u32>()
+ self.rows.primary_capacities.capacity() * std::mem::size_of::<u32>()
+ self.primary_sorted.capacity() * std::mem::size_of::<bool>();
let overflow_reserved: usize = self
.overflow_chunks
.iter()
.map(|(_, chunks)| chunks.iter().map(|chunk| chunk.capacity()).sum::<usize>())
.sum();
let live_heap: usize = self.live_sets.heap_bytes_total();
let live_sets = self.live_sets.index_bytes() + live_heap;
arrays
+ overflow_reserved * slot_bytes
+ self.overflow_chunks.index_bytes()
+ live_sets
+ std::mem::size_of::<Self>()
}
pub fn fragmentation_ratio(&self) -> f32 {
if self.total_edge_capacity == 0 {
return 0.0;
}
let active_edges = self.edge_count as usize;
self.total_edge_capacity.saturating_sub(active_edges) as f32
/ self.total_edge_capacity as f32
}
pub(crate) fn wasted_bytes_estimate(&self) -> usize {
let active_edges = self.edge_count as usize;
let slot_bytes = std::mem::size_of::<HotNbr>() + std::mem::size_of::<ColdStamps>();
self.total_edge_capacity.saturating_sub(active_edges) * slot_bytes
}
pub fn get_fragmentation_stats(&self) -> FragmentationStats {
let live_edges = self.edge_count as usize;
let mut physical_entries = 0usize;
for vid in 0..self.vertex_capacity() {
physical_entries += self.rows.degrees[vid] as usize;
}
for (_, chunks) in self.overflow_chunks.iter() {
for chunk in chunks {
physical_entries += chunk.len();
}
}
let dead_entries = physical_entries.saturating_sub(live_edges);
let wasted_capacity = self.total_edge_capacity.saturating_sub(live_edges);
FragmentationStats::with_dead_info(
self.total_edge_capacity,
live_edges,
dead_entries,
wasted_capacity,
)
}
}