Skip to content

Commit

Permalink
Move cgroup limits computation into its own function to split it out …
Browse files Browse the repository at this point in the history
…from the "normal" memory values
  • Loading branch information
GuillaumeGomez committed Oct 31, 2023
1 parent 28e3b2b commit 345d114
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 38 deletions.
34 changes: 34 additions & 0 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,9 @@ impl System {
/// let s = System::new_all();
/// println!("{} bytes", s.total_memory());
/// ```
///
/// On Linux, if you want to see this information with the limit of your cgroup, take a look
/// at [`cgroup_limits`](System::cgroup_limits).
pub fn total_memory(&self) -> u64 {
self.inner.total_memory()
}
Expand Down Expand Up @@ -546,6 +549,26 @@ impl System {
self.inner.used_swap()
}

/// Retrieves the limits for the current cgroup (if any), otherwise it returns `None`.
///
/// This information is computed every time the method is called.
///
/// ⚠️ You need to have run [`refresh_memory`](System::refresh_memory) at least once before
/// calling this method.
///
/// ⚠️ This method is only implemented for Linux. It always returns `None` for all other
/// systems.
///
/// ```no_run
/// use sysinfo::System;
///
/// let s = System::new_all();
/// println!("limits: {:?}", s.cgroup_limits());
/// ```
pub fn cgroup_limits(&self) -> Option<CGroupLimits> {
self.inner.cgroup_limits()
}

/// Returns system uptime (in seconds).
///
/// ```no_run
Expand Down Expand Up @@ -2445,6 +2468,17 @@ impl std::fmt::Display for Signal {
}
}

/// Contains memory limits for the current process.
#[derive(Default, Debug, Clone)]
pub struct CGroupLimits {
/// Total memory (in bytes) for the current cgroup.
pub total_memory: u64,
/// Free memory (in bytes) for the current cgroup.
pub free_memory: u64,
/// Free swap (in bytes) for the current cgroup.
pub free_swap: u64,
}

/// A struct representing system load average value.
///
/// It is returned by [`System::load_average`][crate::System::load_average].
Expand Down
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ cfg_if::cfg_if! {
}

pub use crate::common::{
get_current_pid, Component, Components, Cpu, CpuRefreshKind, Disk, DiskKind, DiskUsage, Disks,
Gid, Group, LoadAvg, MacAddr, NetworkData, Networks, NetworksIter, Pid, Process,
ProcessRefreshKind, ProcessStatus, RefreshKind, Signal, System, Uid, User, Users,
get_current_pid, CGroupLimits, Component, Components, Cpu, CpuRefreshKind, Disk, DiskKind,
DiskUsage, Disks, Gid, Group, LoadAvg, MacAddr, NetworkData, Networks, NetworksIter, Pid,
Process, ProcessRefreshKind, ProcessStatus, RefreshKind, Signal, System, Uid, User, Users,
};

pub(crate) use crate::sys::{
Expand Down
16 changes: 16 additions & 0 deletions src/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,22 @@ impl serde::Serialize for crate::System {
}
}

impl Serialize for crate::CGroupLimits {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
// `3` corresponds to the number of fields.
let mut state = serializer.serialize_struct("CGroupLimits", 3)?;

state.serialize_field("total_memory", &self.total_memory())?;
state.serialize_field("free_memory", &self.free_memory())?;
state.serialize_field("free_swap", &self.free_swap())?;

state.end()
}
}

impl Serialize for crate::Networks {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand Down
4 changes: 4 additions & 0 deletions src/unix/apple/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ impl SystemInner {
}
}

pub(crate) fn cgroup_limits(&self) -> Option<crate::CGroupLimits> {
None
}

pub(crate) fn refresh_cpu_specifics(&mut self, refresh_kind: CpuRefreshKind) {
self.cpus.refresh(refresh_kind, self.port);
}
Expand Down
4 changes: 4 additions & 0 deletions src/unix/freebsd/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ impl SystemInner {
self.swap_used = swap_used;
}

pub(crate) fn cgroup_limits(&self) -> Option<crate::CGroupLimits> {
None
}

pub(crate) fn refresh_cpu_specifics(&mut self, refresh_kind: CpuRefreshKind) {
self.cpus.refresh(refresh_kind)
}
Expand Down
88 changes: 53 additions & 35 deletions src/unix/linux/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,43 +224,10 @@ impl SystemInner {
.saturating_add(self.mem_slab_reclaimable)
.saturating_sub(self.mem_shmem);
}

self.refresh_cgroup();
}

fn refresh_cgroup(&mut self) {
if let (Some(mem_cur), Some(mem_max)) = (
read_u64("/sys/fs/cgroup/memory.current"),
read_u64("/sys/fs/cgroup/memory.max"),
) {
// cgroups v2
self.mem_total = min(mem_max, self.mem_total);
self.mem_free = self.mem_total.saturating_sub(mem_cur);
self.mem_available = self.mem_free;

if let Some(swap_cur) = read_u64("/sys/fs/cgroup/memory.swap.current") {
self.swap_free = self.swap_total.saturating_sub(swap_cur);
}

read_table("/sys/fs/cgroup/memory.stat", ' ', |key, value| {
let field = match key {
"slab_reclaimable" => &mut self.mem_slab_reclaimable,
"file" => &mut self.mem_page_cache,
"shmem" => &mut self.mem_shmem,
_ => return,
};
*field = value;
self.mem_free = self.mem_free.saturating_sub(value);
});
} else if let (Some(mem_cur), Some(mem_max)) = (
// cgroups v1
read_u64("/sys/fs/cgroup/memory/memory.usage_in_bytes"),
read_u64("/sys/fs/cgroup/memory/memory.limit_in_bytes"),
) {
self.mem_total = min(mem_max, self.mem_total);
self.mem_free = self.mem_total.saturating_sub(mem_cur);
self.mem_available = self.mem_free;
}
pub(crate) fn cgroup_limits(&self) -> Option<crate::CGroupLimits> {
crate::CGroupLimits::new(self)
}

pub(crate) fn refresh_cpu_specifics(&mut self, refresh_kind: CpuRefreshKind) {
Expand Down Expand Up @@ -540,6 +507,57 @@ where
}
}

impl crate::CGroupLimits {
fn new(sys: &SystemInner) -> Option<Self> {
assert!(
sys.mem_total != 0,
"You need to call System::refresh_memory before trying to get cgroup limits!",
);
if let (Some(mem_cur), Some(mem_max)) = (
read_u64("/sys/fs/cgroup/memory.current"),
read_u64("/sys/fs/cgroup/memory.max"),
) {
// cgroups v2

let mut limits = Self {
total_memory: sys.mem_total,
free_memory: sys.mem_free,
free_swap: sys.swap_free,
};

limits.total_memory = min(mem_max, sys.mem_total);
limits.free_memory = limits.total_memory.saturating_sub(mem_cur);

if let Some(swap_cur) = read_u64("/sys/fs/cgroup/memory.swap.current") {
limits.free_swap = sys.swap_total.saturating_sub(swap_cur);
}

read_table("/sys/fs/cgroup/memory.stat", ' ', |_key, value| {
limits.free_memory = limits.free_memory.saturating_sub(value);
});

Some(limits)
} else if let (Some(mem_cur), Some(mem_max)) = (
// cgroups v1
read_u64("/sys/fs/cgroup/memory/memory.usage_in_bytes"),
read_u64("/sys/fs/cgroup/memory/memory.limit_in_bytes"),
) {
let mut limits = Self {
total_memory: sys.mem_total,
free_memory: sys.mem_free,
free_swap: sys.swap_free,
};

limits.total_memory = min(mem_max, sys.mem_total);
limits.free_memory = limits.total_memory.saturating_sub(mem_cur);

Some(limits)
} else {
None
}
}
}

#[derive(PartialEq, Eq)]
enum InfoType {
/// The end-user friendly name of:
Expand Down
4 changes: 4 additions & 0 deletions src/unknown/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ impl SystemInner {

pub(crate) fn refresh_memory(&mut self) {}

pub(crate) fn cgroup_limits(&self) -> Option<crate::CGroupLimits> {
None
}

pub(crate) fn refresh_cpu_specifics(&mut self, _refresh_kind: CpuRefreshKind) {}

pub(crate) fn refresh_processes_specifics(&mut self, _refresh_kind: ProcessRefreshKind) {}
Expand Down
4 changes: 4 additions & 0 deletions src/windows/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@ impl SystemInner {
}
}

pub(crate) fn cgroup_limits(&self) -> Option<crate::CGroupLimits> {
None
}

#[allow(clippy::map_entry)]
pub(crate) fn refresh_process_specifics(
&mut self,
Expand Down

0 comments on commit 345d114

Please sign in to comment.