#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct JemallocStats {
pub allocated_bytes: u64,
pub active_bytes: u64,
pub metadata_bytes: u64,
pub resident_bytes: u64,
pub mapped_bytes: u64,
pub retained_bytes: u64,
}
impl JemallocStats {
#[must_use]
pub fn observed_usage_bytes(self, process_bytes: u64) -> u64 {
process_bytes
.max(self.resident_bytes)
.max(self.allocated_bytes)
}
}
pub trait JemallocStatsSource: Send + Sync {
fn read(&self) -> JemallocStats;
}
pub struct NoJemallocStats;
impl JemallocStatsSource for NoJemallocStats {
fn read(&self) -> JemallocStats {
JemallocStats::default()
}
}
#[cfg(feature = "jemalloc")]
pub use system::SystemJemallocStats;
#[cfg(feature = "jemalloc")]
mod system {
use tikv_jemalloc_ctl::{epoch, epoch_mib, stats};
use super::{JemallocStats, JemallocStatsSource};
pub struct SystemJemallocStats {
epoch: epoch_mib,
allocated: stats::allocated_mib,
active: stats::active_mib,
metadata: stats::metadata_mib,
resident: stats::resident_mib,
mapped: stats::mapped_mib,
retained: stats::retained_mib,
}
impl SystemJemallocStats {
#[must_use]
pub fn new() -> Option<Self> {
Some(Self {
epoch: epoch::mib().ok()?,
allocated: stats::allocated::mib().ok()?,
active: stats::active::mib().ok()?,
metadata: stats::metadata::mib().ok()?,
resident: stats::resident::mib().ok()?,
mapped: stats::mapped::mib().ok()?,
retained: stats::retained::mib().ok()?,
})
}
}
impl JemallocStatsSource for SystemJemallocStats {
fn read(&self) -> JemallocStats {
if self.epoch.advance().is_err() {
return JemallocStats::default();
}
JemallocStats {
allocated_bytes: self.allocated.read().unwrap_or(0) as u64,
active_bytes: self.active.read().unwrap_or(0) as u64,
metadata_bytes: self.metadata.read().unwrap_or(0) as u64,
resident_bytes: self.resident.read().unwrap_or(0) as u64,
mapped_bytes: self.mapped.read().unwrap_or(0) as u64,
retained_bytes: self.retained.read().unwrap_or(0) as u64,
}
}
}
}