From dcb0ae84444a460452d1059b5d17150f94e8eccc Mon Sep 17 00:00:00 2001 From: Herbert Wolverson Date: Tue, 14 Feb 2023 21:27:37 +0000 Subject: [PATCH] Add an additional NUM_CPUS atomic to store the actual size. CPU utilization is updated in a lock-free array of atomics. Another lock removed (and another unmeasurably small gain) --- src/rust/Cargo.lock | 1 + src/rust/lqos_node_manager/Cargo.toml | 1 + .../src/tracker/cache/cpu_ram.rs | 28 +++++++++++++------ .../src/tracker/cache_manager.rs | 11 +++++--- src/rust/lqos_node_manager/src/tracker/mod.rs | 12 +++++--- 5 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 139b4109..d0a0ee41 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -1359,6 +1359,7 @@ dependencies = [ "lqos_config", "lqos_utils", "nix", + "once_cell", "parking_lot", "rocket", "rocket_async_compression", diff --git a/src/rust/lqos_node_manager/Cargo.toml b/src/rust/lqos_node_manager/Cargo.toml index d2266718..8c7bf029 100644 --- a/src/rust/lqos_node_manager/Cargo.toml +++ b/src/rust/lqos_node_manager/Cargo.toml @@ -19,6 +19,7 @@ anyhow = "1" sysinfo = "0" default-net = "0" nix = "0" +once_cell = "1" # Support JemAlloc on supported platforms [target.'cfg(any(target_arch = "x86", target_arch = "x86_64"))'.dependencies] diff --git a/src/rust/lqos_node_manager/src/tracker/cache/cpu_ram.rs b/src/rust/lqos_node_manager/src/tracker/cache/cpu_ram.rs index d7dc8c76..cc9c8112 100644 --- a/src/rust/lqos_node_manager/src/tracker/cache/cpu_ram.rs +++ b/src/rust/lqos_node_manager/src/tracker/cache/cpu_ram.rs @@ -1,12 +1,24 @@ -use std::sync::atomic::AtomicU64; +use std::sync::atomic::{AtomicU64, AtomicU32, AtomicUsize}; +use once_cell::sync::Lazy; -use lazy_static::*; -use parking_lot::RwLock; +const MAX_CPUS_COUNTED: usize = 128; -lazy_static! { - /// Global storage of current CPU usage - pub static ref CPU_USAGE : RwLock> = RwLock::new(Vec::with_capacity(128)); -} +/// Stores overall CPU usage +pub static CPU_USAGE: Lazy<[AtomicU32; MAX_CPUS_COUNTED]> = Lazy::new(build_empty_cpu_list); +/// Total number of CPUs detected +pub static NUM_CPUS: AtomicUsize = AtomicUsize::new(0); + +/// Total RAM used (bytes) pub static RAM_USED: AtomicU64 = AtomicU64::new(0); -pub static TOTAL_RAM: AtomicU64 = AtomicU64::new(0); \ No newline at end of file + +/// Total RAM installed (bytes) +pub static TOTAL_RAM: AtomicU64 = AtomicU64::new(0); + +fn build_empty_cpu_list() -> [AtomicU32; MAX_CPUS_COUNTED] { + let mut temp = Vec::with_capacity(MAX_CPUS_COUNTED); + for _ in 0..MAX_CPUS_COUNTED { + temp.push(AtomicU32::new(0)); + } + temp.try_into().expect("This should never happen, sizes are constant.") +} \ No newline at end of file diff --git a/src/rust/lqos_node_manager/src/tracker/cache_manager.rs b/src/rust/lqos_node_manager/src/tracker/cache_manager.rs index 3c373c0f..5b0d65b6 100644 --- a/src/rust/lqos_node_manager/src/tracker/cache_manager.rs +++ b/src/rust/lqos_node_manager/src/tracker/cache_manager.rs @@ -53,12 +53,15 @@ pub async fn update_tracking() { sys.refresh_cpu(); sys.refresh_memory(); - let cpu_usage = sys + + sys .cpus() .iter() - .map(|cpu| cpu.cpu_usage()) - .collect::>(); - *CPU_USAGE.write() = cpu_usage; + .enumerate() + .map(|(i, cpu)| (i, cpu.cpu_usage() as u32)) // Always rounds down + .for_each(|(i, cpu)| CPU_USAGE[i].store(cpu, std::sync::atomic::Ordering::Relaxed)); + + NUM_CPUS.store(sys.cpus().len(), std::sync::atomic::Ordering::Relaxed); RAM_USED.store(sys.used_memory(), std::sync::atomic::Ordering::Relaxed); TOTAL_RAM.store(sys.total_memory(), std::sync::atomic::Ordering::Relaxed); let error = get_data_from_server().await; // Ignoring errors to keep running diff --git a/src/rust/lqos_node_manager/src/tracker/mod.rs b/src/rust/lqos_node_manager/src/tracker/mod.rs index 1fa2d90a..4e47c9eb 100644 --- a/src/rust/lqos_node_manager/src/tracker/mod.rs +++ b/src/rust/lqos_node_manager/src/tracker/mod.rs @@ -2,7 +2,7 @@ mod cache; mod cache_manager; use self::cache::{ CPU_USAGE, CURRENT_THROUGHPUT, HOST_COUNTS, RAM_USED, TOTAL_RAM, RTT_HISTOGRAM, - THROUGHPUT_BUFFER, TOP_10_DOWNLOADERS, WORST_10_RTT, + THROUGHPUT_BUFFER, TOP_10_DOWNLOADERS, WORST_10_RTT, NUM_CPUS, }; use crate::{auth_guard::AuthGuard, tracker::cache::ThroughputPerSecond}; pub use cache::{SHAPED_DEVICES, UNKNOWN_DEVICES}; @@ -70,10 +70,14 @@ pub fn throughput_ring(_auth: AuthGuard) -> Json> { } #[get("/api/cpu")] -pub fn cpu_usage(_auth: AuthGuard) -> Json> { - let cpu_usage = CPU_USAGE.read().clone(); +pub fn cpu_usage(_auth: AuthGuard) -> Json> { + let usage: Vec = CPU_USAGE + .iter() + .take(NUM_CPUS.load(std::sync::atomic::Ordering::Relaxed)) + .map(|cpu| cpu.load(std::sync::atomic::Ordering::Relaxed)) + .collect(); - Json(cpu_usage) + Json(usage) } #[get("/api/ram")]