lesavka: improve process cpu sampling
This commit is contained in:
parent
7cb0a4d655
commit
57cd7aac33
@ -4,7 +4,7 @@ path = "src/main.rs"
|
||||
|
||||
[package]
|
||||
name = "lesavka_client"
|
||||
version = "0.11.2"
|
||||
version = "0.11.3"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "lesavka_common"
|
||||
version = "0.11.2"
|
||||
version = "0.11.3"
|
||||
edition = "2024"
|
||||
build = "build.rs"
|
||||
|
||||
|
||||
@ -17,6 +17,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn banner_includes_version() {
|
||||
assert_eq!(banner("0.11.2"), "lesavka-common CLI (v0.11.2)");
|
||||
assert_eq!(banner("0.11.3"), "lesavka-common CLI (v0.11.3)");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
use std::time::Instant;
|
||||
use std::{process::Command, sync::OnceLock};
|
||||
|
||||
/// Sample per-process CPU pressure from Linux procfs.
|
||||
///
|
||||
@ -41,10 +42,43 @@ impl ProcessCpuSampler {
|
||||
}
|
||||
|
||||
fn read_process_runtime_ns() -> Option<u64> {
|
||||
read_process_runtime_from_stat().or_else(read_process_runtime_from_schedstat)
|
||||
}
|
||||
|
||||
fn read_process_runtime_from_stat() -> Option<u64> {
|
||||
let text = std::fs::read_to_string("/proc/self/stat").ok()?;
|
||||
let close = text.rfind(')')?;
|
||||
let rest = text.get(close + 2..)?;
|
||||
let fields: Vec<&str> = rest.split_whitespace().collect();
|
||||
let utime_ticks = fields.get(11)?.parse::<u64>().ok()?;
|
||||
let stime_ticks = fields.get(12)?.parse::<u64>().ok()?;
|
||||
let total_ticks = utime_ticks.saturating_add(stime_ticks);
|
||||
let ticks_per_second = *clock_ticks_per_second()?;
|
||||
Some(total_ticks.saturating_mul(1_000_000_000) / ticks_per_second.max(1))
|
||||
}
|
||||
|
||||
fn read_process_runtime_from_schedstat() -> Option<u64> {
|
||||
let text = std::fs::read_to_string("/proc/self/schedstat").ok()?;
|
||||
text.split_whitespace().next()?.parse::<u64>().ok()
|
||||
}
|
||||
|
||||
fn clock_ticks_per_second() -> Option<&'static u64> {
|
||||
static CLOCK_TICKS_PER_SECOND: OnceLock<Option<u64>> = OnceLock::new();
|
||||
CLOCK_TICKS_PER_SECOND
|
||||
.get_or_init(|| {
|
||||
let output = Command::new("getconf").arg("CLK_TCK").output().ok()?;
|
||||
if !output.status.success() {
|
||||
return None;
|
||||
}
|
||||
String::from_utf8(output.stdout)
|
||||
.ok()?
|
||||
.trim()
|
||||
.parse::<u64>()
|
||||
.ok()
|
||||
})
|
||||
.as_ref()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@ -56,6 +90,11 @@ mod tests {
|
||||
assert!(read_process_runtime_ns().is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clock_tick_lookup_reads() {
|
||||
assert!(clock_ticks_per_second().is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sampler_returns_percentage_after_two_samples() {
|
||||
let mut sampler = ProcessCpuSampler::new();
|
||||
|
||||
@ -10,7 +10,7 @@ bench = false
|
||||
|
||||
[package]
|
||||
name = "lesavka_server"
|
||||
version = "0.11.2"
|
||||
version = "0.11.3"
|
||||
edition = "2024"
|
||||
autobins = false
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user