From f62b5274d24928bcf66ee0dc456869644510d06d Mon Sep 17 00:00:00 2001 From: jasonwitty Date: Mon, 25 Aug 2025 22:35:01 -0700 Subject: [PATCH] optimize non linux metrics collection --- Cargo.lock | 2 +- socktop_agent/Cargo.toml | 2 +- socktop_agent/src/metrics.rs | 60 ++++++++++++++++++++++-------------- 3 files changed, 39 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5b66c81..f0414a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2187,7 +2187,7 @@ dependencies = [ [[package]] name = "socktop_agent" -version = "1.40.0" +version = "1.40.1" dependencies = [ "anyhow", "assert_cmd", diff --git a/socktop_agent/Cargo.toml b/socktop_agent/Cargo.toml index 2adc385..41186e8 100644 --- a/socktop_agent/Cargo.toml +++ b/socktop_agent/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "socktop_agent" -version = "1.40.0" +version = "1.40.1" authors = ["Jason Witty "] description = "Remote system monitor over WebSocket, TUI like top" edition = "2021" diff --git a/socktop_agent/src/metrics.rs b/socktop_agent/src/metrics.rs index 35600f9..e007da2 100644 --- a/socktop_agent/src/metrics.rs +++ b/socktop_agent/src/metrics.rs @@ -416,6 +416,7 @@ pub async fn collect_processes_all(state: &AppState) -> ProcessesPayload { } } } + // First refresh: everything (establish baseline including memory/name etc.) { let mut sys = state.sys.lock().await; sys.refresh_processes_specifics( @@ -424,34 +425,47 @@ pub async fn collect_processes_all(state: &AppState) -> ProcessesPayload { ProcessRefreshKind::everything().without_tasks(), ); } - // Release lock during sleep interval - sleep(Duration::from_millis(250)).await; - { + // Sleep briefly to allow cpu deltas to accumulate; 200-250ms is typical; we keep 200ms to lower agent overhead. + sleep(Duration::from_millis(200)).await; + // Second refresh: only CPU counters (lighter than full everything) to reduce overhead. + let (total_count, procs) = { let mut sys = state.sys.lock().await; - sys.refresh_processes_specifics( - ProcessesToUpdate::All, - false, - ProcessRefreshKind::everything().without_tasks(), - ); + let cpu_only = ProcessRefreshKind::new().with_cpu().without_tasks(); + sys.refresh_processes_specifics(ProcessesToUpdate::All, false, cpu_only); let total_count = sys.processes().len(); - let procs: Vec = sys + let norm = normalize_cpu_enabled(); + let cores = if norm { + sys.cpus().len().max(1) as f32 + } else { + 1.0 + }; + let list: Vec = sys .processes() .values() - .map(|p| ProcessInfo { - pid: p.pid().as_u32(), - name: p.name().to_string_lossy().into_owned(), - cpu_usage: p.cpu_usage(), - mem_bytes: p.memory(), + .map(|p| { + let raw = p.cpu_usage(); + let cpu = if norm { + (raw / cores).clamp(0.0, 100.0) + } else { + raw + }; + ProcessInfo { + pid: p.pid().as_u32(), + name: p.name().to_string_lossy().into_owned(), + cpu_usage: cpu, + mem_bytes: p.memory(), + } }) .collect(); - let payload = ProcessesPayload { - process_count: total_count, - top_processes: procs, - }; - { - let mut cache = state.cache_processes.lock().await; - cache.set(payload.clone()); - } - payload + (total_count, list) + }; + let payload = ProcessesPayload { + process_count: total_count, + top_processes: procs, + }; + { + let mut cache = state.cache_processes.lock().await; + cache.set(payload.clone()); } + payload }