perf: optimize cgroup resource detection with single System instance (#6550)

* perf: optimize cgroup resource detection with single System instance

Consolidate two sysinfo::System instantiations into one for CPU and
memory detection. Pre-compute the metrics basis string ("cgroup"/"host")
in ContainerResources to avoid per-snapshot String allocations in the
memory observability hot path.

Co-Authored-By: heihutu <heihutu@gmail.com>

* style: apply cargo fmt formatting

Co-Authored-By: heihutu <heihutu@gmail.com>

---------

Co-authored-by: heihutu <heihutu@gmail.com>
This commit is contained in:
houseme
2026-08-25 04:07:02 +08:00
committed by GitHub
parent 5c6e1abe7e
commit 4d43f1ea8a
2 changed files with 16 additions and 22 deletions
+14 -20
View File
@@ -62,6 +62,8 @@ pub struct ContainerResources {
pub cgroup_detected: bool, pub cgroup_detected: bool,
/// Whether values were overridden by environment variables. /// Whether values were overridden by environment variables.
pub overridden: bool, pub overridden: bool,
/// Pre-computed basis string for metrics ("cgroup" or "host").
pub basis: &'static str,
} }
impl Default for ContainerResources { impl Default for ContainerResources {
@@ -71,6 +73,7 @@ impl Default for ContainerResources {
memory_bytes: 0, memory_bytes: 0,
cgroup_detected: false, cgroup_detected: false,
overridden: false, overridden: false,
basis: "host",
} }
} }
} }
@@ -205,7 +208,7 @@ mod cgroup {
/// Detection priority: /// Detection priority:
/// 1. Environment variable overrides /// 1. Environment variable overrides
/// 2. cgroup v1/v2 limits (Linux only) /// 2. cgroup v1/v2 limits (Linux only)
/// 3. Host values from sysinfo /// 3. Host values from sysinfo (single System instance for both CPU and memory)
fn detect_container_resources() -> ContainerResources { fn detect_container_resources() -> ContainerResources {
// Check if cgroup detection is disabled // Check if cgroup detection is disabled
let cgroup_disabled = std::env::var(ENV_DISABLE_CGROUP_DETECTION) let cgroup_disabled = std::env::var(ENV_DISABLE_CGROUP_DETECTION)
@@ -234,30 +237,25 @@ fn detect_container_resources() -> ContainerResources {
let overridden = override_cores.is_some() || override_memory.is_some(); let overridden = override_cores.is_some() || override_memory.is_some();
// Get host values for fallback // Get host values from a single sysinfo::System instance (avoids double init)
let host_cores = { let (host_cores, host_memory) = {
let mut sys = let mut sys = sysinfo::System::new_with_specifics(sysinfo::RefreshKind::everything().without_processes());
sysinfo::System::new_with_specifics(sysinfo::RefreshKind::everything().without_memory().without_processes());
sys.refresh_cpu_all(); sys.refresh_cpu_all();
sys.cpus().len().max(1)
};
let host_memory = {
let mut sys = sysinfo::System::new();
sys.refresh_memory(); sys.refresh_memory();
sys.total_memory() (sys.cpus().len().max(1), sys.total_memory())
}; };
// Determine effective values: override > cgroup > host // Determine effective values: override > cgroup > host
let cpu_cores = override_cores.or(cgroup_cpus).unwrap_or(host_cores).max(1); let cpu_cores = override_cores.or(cgroup_cpus).unwrap_or(host_cores).max(1);
let memory_bytes = override_memory.or(cgroup_memory).unwrap_or(host_memory); let memory_bytes = override_memory.or(cgroup_memory).unwrap_or(host_memory);
let basis = if cgroup_detected { "cgroup" } else { "host" };
ContainerResources { ContainerResources {
cpu_cores, cpu_cores,
memory_bytes, memory_bytes,
cgroup_detected, cgroup_detected,
overridden, overridden,
basis,
} }
} }
@@ -273,12 +271,13 @@ pub fn container_resources() -> &'static ContainerResources {
/// Should be called once during startup to help operators verify detection. /// Should be called once during startup to help operators verify detection.
pub fn log_container_resources() { pub fn log_container_resources() {
let res = container_resources(); let res = container_resources();
let memory_mib = res.memory_bytes / (1024 * 1024);
if res.overridden { if res.overridden {
tracing::info!( tracing::info!(
cpu_cores = res.cpu_cores, cpu_cores = res.cpu_cores,
memory_bytes = res.memory_bytes, memory_bytes = res.memory_bytes,
memory_mib = res.memory_bytes / (1024 * 1024), memory_mib,
cgroup_detected = res.cgroup_detected, cgroup_detected = res.cgroup_detected,
"container resources (overridden by environment variables)" "container resources (overridden by environment variables)"
); );
@@ -286,7 +285,7 @@ pub fn log_container_resources() {
tracing::info!( tracing::info!(
cpu_cores = res.cpu_cores, cpu_cores = res.cpu_cores,
memory_bytes = res.memory_bytes, memory_bytes = res.memory_bytes,
memory_mib = res.memory_bytes / (1024 * 1024), memory_mib,
"container resources (detected from cgroup)" "container resources (detected from cgroup)"
); );
} else { } else {
@@ -298,12 +297,6 @@ pub fn log_container_resources() {
} }
} }
/// Get the memory basis string for metrics.
pub fn memory_basis() -> &'static str {
let res = container_resources();
if res.cgroup_detected { "cgroup" } else { "host" }
}
// ============================================================================ // ============================================================================
// Tests // Tests
// ============================================================================ // ============================================================================
@@ -319,6 +312,7 @@ mod tests {
assert_eq!(resources.memory_bytes, 0); assert_eq!(resources.memory_bytes, 0);
assert!(!resources.cgroup_detected); assert!(!resources.cgroup_detected);
assert!(!resources.overridden); assert!(!resources.overridden);
assert_eq!(resources.basis, "host");
} }
#[test] #[test]
+2 -2
View File
@@ -391,8 +391,8 @@ pub fn memory_observability_controller_snapshot(ctx: &CancellationToken) -> Memo
/// Record the effective memory total and its basis (host or cgroup). /// Record the effective memory total and its basis (host or cgroup).
fn record_effective_memory(total_bytes: u64) { fn record_effective_memory(total_bytes: u64) {
let basis = crate::cgroup_resources::memory_basis(); let basis = crate::cgroup_resources::container_resources().basis;
metrics::gauge!("rustfs_memory_effective_total_bytes", "basis" => basis.to_string()).set(total_bytes as f64); metrics::gauge!("rustfs_memory_effective_total_bytes", "basis" => basis).set(total_bytes as f64);
} }
/// Record container resource detection results. /// Record container resource detection results.