lesavka: improve process cpu sampling
This commit is contained in:
parent
7cb0a4d655
commit
57cd7aac33
@ -4,7 +4,7 @@ path = "src/main.rs"
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "lesavka_client"
|
name = "lesavka_client"
|
||||||
version = "0.11.2"
|
version = "0.11.3"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lesavka_common"
|
name = "lesavka_common"
|
||||||
version = "0.11.2"
|
version = "0.11.3"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,6 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn banner_includes_version() {
|
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)]
|
#![forbid(unsafe_code)]
|
||||||
|
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
use std::{process::Command, sync::OnceLock};
|
||||||
|
|
||||||
/// Sample per-process CPU pressure from Linux procfs.
|
/// Sample per-process CPU pressure from Linux procfs.
|
||||||
///
|
///
|
||||||
@ -41,10 +42,43 @@ impl ProcessCpuSampler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn read_process_runtime_ns() -> Option<u64> {
|
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()?;
|
let text = std::fs::read_to_string("/proc/self/schedstat").ok()?;
|
||||||
text.split_whitespace().next()?.parse::<u64>().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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -56,6 +90,11 @@ mod tests {
|
|||||||
assert!(read_process_runtime_ns().is_some());
|
assert!(read_process_runtime_ns().is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn clock_tick_lookup_reads() {
|
||||||
|
assert!(clock_ticks_per_second().is_some());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn sampler_returns_percentage_after_two_samples() {
|
fn sampler_returns_percentage_after_two_samples() {
|
||||||
let mut sampler = ProcessCpuSampler::new();
|
let mut sampler = ProcessCpuSampler::new();
|
||||||
|
|||||||
@ -10,7 +10,7 @@ bench = false
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "lesavka_server"
|
name = "lesavka_server"
|
||||||
version = "0.11.2"
|
version = "0.11.3"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
autobins = false
|
autobins = false
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user