summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClement Tsang <34804052+ClementTsang@users.noreply.github.com>2021-07-17 21:25:05 -0400
committerGitHub <noreply@github.com>2021-07-17 21:25:05 -0400
commit7f24e6286735abcee6c3137dd9c22a7a178740a3 (patch)
tree0c47ab7f10e8f21018ef703f2e8f449bde222c0d
parent4e07a28e172f0767edbb9d508f4fa9e2af7b25cd (diff)
bug: switch over to procfs for linux mem usage (#547)
Swap to manually calculating the mem total and usage via procfs. The usage calculation is now: total - (free + cached + buffers + slab_reclaimable - shmem) This follows the same usage calculation as htop. See the PR for more details.
-rw-r--r--CHANGELOG.md6
-rw-r--r--docs/content/usage/widgets/memory.md10
-rw-r--r--src/app/data_harvester/memory/general.rs (renamed from src/app/data_harvester/memory/heim.rs)37
-rw-r--r--src/app/data_harvester/memory/mod.rs4
4 files changed, 42 insertions, 15 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e0ac5aa4..0a5ff9e8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,7 +12,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Bug Fixes
- [#542](https://github.com/ClementTsang/bottom/pull/542): Fixes missing config options in the default generated config file.
-- [#545](https://github.com/ClementTsang/bottom/pull/545): Fixes inaccurate memory usage/totals in macOS and Linux.
+- [#545](https://github.com/ClementTsang/bottom/pull/545): Fixes inaccurate memory usage/totals in macOS and Linux, switch unit to binary prefix.
+
+## Changes
+
+- [#547](https://github.com/ClementTsang/bottom/pull/547): Switch memory usage calculation to match htop.
## [0.6.2] - 2021-06-26
diff --git a/docs/content/usage/widgets/memory.md b/docs/content/usage/widgets/memory.md
index f92f18a8..f25dbe36 100644
--- a/docs/content/usage/widgets/memory.md
+++ b/docs/content/usage/widgets/memory.md
@@ -28,3 +28,13 @@ Note that key bindings are generally case-sensitive.
| Binding | Action |
| ------------ | -------------------------------------------------------------- |
| ++"Scroll"++ | Scrolling up or down zooms in or out of the graph respectively |
+
+## Calculations
+
+Memory usage is calculated using the following formula based on values from `/proc/meminfo` (based on [htop's implementation](https://github.com/htop-dev/htop/blob/976c6123f41492aaf613b9d172eef1842fb7b0a3/linux/LinuxProcessList.c#L1584)):
+
+```
+MemTotal - MemFree - Buffers - (Cached + SReclaimable - Shmem)
+```
+
+You can find more info on `/proc/meminfo` and its fields [here](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/s2-proc-meminfo).
diff --git a/src/app/data_harvester/memory/heim.rs b/src/app/data_harvester/memory/general.rs
index 29f16910..4af287d7 100644
--- a/src/app/data_harvester/memory/heim.rs
+++ b/src/app/data_harvester/memory/general.rs
@@ -23,27 +23,38 @@ pub async fn get_mem_data(
}
pub async fn get_ram_data() -> crate::utils::error::Result<Option<MemHarvest>> {
- let memory = heim::memory::memory().await?;
-
let (mem_total_in_kib, mem_used_in_kib) = {
#[cfg(target_os = "linux")]
{
- use heim::memory::os::linux::MemoryExt;
- use heim::units::information::kilobyte;
+ let mem_info = procfs::Meminfo::new()?;
- // For Linux, the "kilobyte" value in the .total call is actually kibibytes - see
- // https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/s2-proc-meminfo
+ // Let's preface this by saying that memory usage calculations are... not straightforward.
+ // There are conflicting implementations everywhere.
+ //
+ // Now that we've added this preface (mainly for future reference), the current implementation below for usage
+ // is based on htop's calculation formula. See
+ // https://github.com/htop-dev/htop/blob/976c6123f41492aaf613b9d172eef1842fb7b0a3/linux/LinuxProcessList.c#L1584
+ // for implementation details as of writing.
//
- // Heim parses this as kilobytes (https://github.com/heim-rs/heim/blob/master/heim-memory/src/sys/linux/memory.rs#L82)
- // even though it probably shouldn't...
+ // Another implementation, commonly used in other things, is to skip the shmem part of the calculation,
+ // which matches gopsutil and stuff like free.
- (
- memory.total().get::<kilobyte>(),
- memory.used().get::<kilobyte>(),
- )
+ 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 used = if total >= used_diff {
+ total - used_diff
+ } else {
+ total - mem_info.mem_free
+ };
+
+ (total, used)
}
#[cfg(target_os = "macos")]
{
+ let memory = heim::memory::memory().await?;
+
use heim::memory::os::macos::MemoryExt;
use heim::units::information::kibibyte;
(
@@ -53,6 +64,8 @@ pub async fn get_ram_data() -> crate::utils::error::Result<Option<MemHarvest>> {
}
#[cfg(target_os = "windows")]
{
+ let memory = heim::memory::memory().await?;
+
use heim::units::information::kibibyte;
let mem_total_in_kib = memory.total().get::<kibibyte>();
(
diff --git a/src/app/data_harvester/memory/mod.rs b/src/app/data_harvester/memory/mod.rs
index 588a3c3b..25fccf59 100644
--- a/src/app/data_harvester/memory/mod.rs
+++ b/src/app/data_harvester/memory/mod.rs
@@ -4,7 +4,7 @@
cfg_if::cfg_if! {
if #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] {
- pub mod heim;
- pub use self::heim::*;
+ pub mod general;
+ pub use self::general::*;
}
}