use std::sync::Mutex;
use sysinfo::{Pid, ProcessRefreshKind, ProcessesToUpdate, System};
pub trait RssSource: Send + Sync {
fn read_rss_bytes(&self) -> u64;
fn total_ram_bytes(&self) -> u64 {
panic!("RssSource::total_ram_bytes must be implemented");
}
}
pub struct SystemRss {
inner: Mutex<SystemRssInner>,
}
struct SystemRssInner {
system: System,
pid: Pid,
}
impl SystemRss {
#[must_use]
pub fn new() -> Self {
let pid = sysinfo::get_current_pid().expect("sysinfo cannot resolve current pid");
let mut system = System::new();
system.refresh_memory();
Self {
inner: Mutex::new(SystemRssInner { system, pid }),
}
}
}
impl Default for SystemRss {
fn default() -> Self {
Self::new()
}
}
impl RssSource for SystemRss {
fn read_rss_bytes(&self) -> u64 {
let mut guard = self.inner.lock().expect("system-rss lock");
let pid = guard.pid;
let refresh = ProcessRefreshKind::nothing().with_memory();
let refreshed = guard.system.refresh_processes_specifics(
ProcessesToUpdate::Some(&[pid]),
true,
refresh,
);
assert_eq!(refreshed, 1, "sysinfo did not refresh the current process");
guard
.system
.process(pid)
.map(sysinfo::Process::memory)
.expect("sysinfo lost the current process")
}
fn total_ram_bytes(&self) -> u64 {
let mut guard = self.inner.lock().expect("system-rss lock");
guard.system.refresh_memory();
guard.system.total_memory()
}
}