mirror of
https://github.com/ClementTsang/bottom.git
synced 2025-07-28 16:14:16 +02:00
refactor: switch to manual implementation of meminfo parse (#548)
Manually parse `/proc/meminfo` for the purposes of memory usage.
This commit is contained in:
parent
7f24e62867
commit
2736dc9b35
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -258,6 +258,7 @@ dependencies = [
|
|||||||
"procfs",
|
"procfs",
|
||||||
"regex",
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
|
"smol",
|
||||||
"sysinfo",
|
"sysinfo",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"toml",
|
"toml",
|
||||||
|
@ -68,8 +68,9 @@ log = { version = "0.4.14", optional = true }
|
|||||||
libc = "0.2.86"
|
libc = "0.2.86"
|
||||||
|
|
||||||
[target.'cfg(target_os = "linux")'.dependencies]
|
[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"
|
procfs = "0.9.1"
|
||||||
|
smol = "1.2.5"
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.dependencies]
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
heim = { version = "0.1.0-rc.1", features = ["cpu", "disk", "memory", "net"] }
|
heim = { version = "0.1.0-rc.1", features = ["cpu", "disk", "memory", "net"] }
|
||||||
|
@ -8,7 +8,7 @@ The memory widget provides a visual representation of RAM and swap usage over ti
|
|||||||
|
|
||||||
## Features
|
## 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.
|
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.
|
One can also adjust the displayed time range through either the keyboard or mouse, with a range of 30s to 600s.
|
||||||
|
@ -26,7 +26,48 @@ pub async fn get_ram_data() -> crate::utils::error::Result<Option<MemHarvest>> {
|
|||||||
let (mem_total_in_kib, mem_used_in_kib) = {
|
let (mem_total_in_kib, mem_used_in_kib) = {
|
||||||
#[cfg(target_os = "linux")]
|
#[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::<u64>() {
|
||||||
|
*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.
|
// Let's preface this by saying that memory usage calculations are... not straightforward.
|
||||||
// There are conflicting implementations everywhere.
|
// There are conflicting implementations everywhere.
|
||||||
@ -39,14 +80,13 @@ pub async fn get_ram_data() -> crate::utils::error::Result<Option<MemHarvest>> {
|
|||||||
// Another implementation, commonly used in other things, is to skip the shmem part of the calculation,
|
// Another implementation, commonly used in other things, is to skip the shmem part of the calculation,
|
||||||
// which matches gopsutil and stuff like free.
|
// which matches gopsutil and stuff like free.
|
||||||
|
|
||||||
let total = mem_info.mem_total / 1024;
|
let total = mem_total;
|
||||||
let cached_mem =
|
let cached_mem = cached + s_reclaimable - shmem;
|
||||||
mem_info.cached + mem_info.s_reclaimable.unwrap_or(0) - mem_info.shmem.unwrap_or(0);
|
let used_diff = mem_free + cached_mem + buffers;
|
||||||
let used_diff = (mem_info.mem_free + cached_mem + mem_info.buffers) / 1024;
|
|
||||||
let used = if total >= used_diff {
|
let used = if total >= used_diff {
|
||||||
total - used_diff
|
total - used_diff
|
||||||
} else {
|
} else {
|
||||||
total - mem_info.mem_free
|
total - mem_free
|
||||||
};
|
};
|
||||||
|
|
||||||
(total, used)
|
(total, used)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user