From 2736dc9b35739b9b48d8ac2ad0b5d3671813c725 Mon Sep 17 00:00:00 2001 From: Clement Tsang <34804052+ClementTsang@users.noreply.github.com> Date: Sat, 17 Jul 2021 22:27:40 -0400 Subject: refactor: switch to manual implementation of meminfo parse (#548) Manually parse `/proc/meminfo` for the purposes of memory usage. --- Cargo.lock | 1 + Cargo.toml | 3 +- docs/content/usage/widgets/memory.md | 2 +- src/app/data_harvester/memory/general.rs | 52 ++++++++++++++++++++++++++++---- 4 files changed, 50 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8b38605d..d4b77036 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -258,6 +258,7 @@ dependencies = [ "procfs", "regex", "serde", + "smol", "sysinfo", "thiserror", "toml", diff --git a/Cargo.toml b/Cargo.toml index c104daa2..e7bdfe3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,8 +68,9 @@ log = { version = "0.4.14", optional = true } libc = "0.2.86" [target.'cfg(target_os = "linux")'.dependencies] -heim = { version = "0.1.0-rc.1", features = ["cpu", "disk", "memory", "net", "sensors"] } +heim = { version = "0.1.0-rc.1", features = ["cpu", "disk", "net", "sensors"] } procfs = "0.9.1" +smol = "1.2.5" [target.'cfg(target_os = "macos")'.dependencies] heim = { version = "0.1.0-rc.1", features = ["cpu", "disk", "memory", "net"] } diff --git a/docs/content/usage/widgets/memory.md b/docs/content/usage/widgets/memory.md index f25dbe36..59d36c9a 100644 --- a/docs/content/usage/widgets/memory.md +++ b/docs/content/usage/widgets/memory.md @@ -8,7 +8,7 @@ The memory widget provides a visual representation of RAM and swap usage over ti ## Features -The legend displays the current usage in terms of percentage and actual usage. +The legend displays the current usage in terms of percentage and actual usage in binary units (KiB, MiB, GiB, etc.). If the total RAM or swap available is 0, then it is automatically hidden from the legend and graph. One can also adjust the displayed time range through either the keyboard or mouse, with a range of 30s to 600s. diff --git a/src/app/data_harvester/memory/general.rs b/src/app/data_harvester/memory/general.rs index 4af287d7..2afe119f 100644 --- a/src/app/data_harvester/memory/general.rs +++ b/src/app/data_harvester/memory/general.rs @@ -26,7 +26,48 @@ pub async fn get_ram_data() -> crate::utils::error::Result> { let (mem_total_in_kib, mem_used_in_kib) = { #[cfg(target_os = "linux")] { - let mem_info = procfs::Meminfo::new()?; + use smol::fs::read_to_string; + let meminfo = read_to_string("/proc/meminfo").await?; + + // All values are in KiB by default. + let mut mem_total = 0; + let mut cached = 0; + let mut s_reclaimable = 0; + let mut shmem = 0; + let mut buffers = 0; + let mut mem_free = 0; + + let mut keys_read: u8 = 0; + const TOTAL_KEYS_NEEDED: u8 = 6; + + for line in meminfo.lines() { + if let Some((label, value)) = line.split_once(':') { + let to_write = match label { + "MemTotal" => &mut mem_total, + "MemFree" => &mut mem_free, + "Buffers" => &mut buffers, + "Cached" => &mut cached, + "Shmem" => &mut shmem, + "SReclaimable" => &mut s_reclaimable, + _ => { + continue; + } + }; + + if let Some((number, _unit)) = value.trim_start().split_once(' ') { + // Parse the value, remember it's in KiB! + if let Ok(number) = number.parse::() { + *to_write = number; + + // We only need a few keys, so we can bail early. + keys_read += 1; + if keys_read == TOTAL_KEYS_NEEDED { + break; + } + } + } + } + } // Let's preface this by saying that memory usage calculations are... not straightforward. // There are conflicting implementations everywhere. @@ -39,14 +80,13 @@ pub async fn get_ram_data() -> crate::utils::error::Result> { // Another implementation, commonly used in other things, is to skip the shmem part of the calculation, // which matches gopsutil and stuff like free. - let total = mem_info.mem_total / 1024; - let cached_mem = - mem_info.cached + mem_info.s_reclaimable.unwrap_or(0) - mem_info.shmem.unwrap_or(0); - let used_diff = (mem_info.mem_free + cached_mem + mem_info.buffers) / 1024; + let total = mem_total; + let cached_mem = cached + s_reclaimable - shmem; + let used_diff = mem_free + cached_mem + buffers; let used = if total >= used_diff { total - used_diff } else { - total - mem_info.mem_free + total - mem_free }; (total, used) -- cgit v1.2.3