Skip to content

Commit f325b47

Browse files
authored
Merge pull request #2160 from bpeetz/correct_memory_calc
memory: Avoid estimating available memory, use kernel estimate instead
2 parents e82c1fc + fe7d621 commit f325b47

File tree

1 file changed

+31
-32
lines changed

1 file changed

+31
-32
lines changed

src/blocks/memory.rs

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ pub async fn run(config: &Config, api: &CommonApi) -> Result<()> {
112112
loop {
113113
let mem_state = Memstate::new().await?;
114114

115-
let mem_total = mem_state.mem_total as f64 * 1024.;
116-
let mem_free = mem_state.mem_free as f64 * 1024.;
115+
let mem_total = mem_state.mem_total as f64;
116+
let mem_free = mem_state.mem_free as f64;
117117

118118
// TODO: possibly remove this as it is confusing to have `mem_total_used` and `mem_used`
119119
// htop and such only display equivalent of `mem_used`
@@ -126,8 +126,7 @@ pub async fn run(config: &Config, api: &CommonApi) -> Result<()> {
126126
min(mem_state.mem_available, mem_state.mem_total)
127127
} else {
128128
mem_state.mem_free
129-
} as f64
130-
* 1024.;
129+
} as f64;
131130

132131
// While zfs_arc_cache can be considered "available" memory,
133132
// it can only free a maximum of (zfs_arc_cache - zfs_arc_min) amount.
@@ -137,34 +136,30 @@ pub async fn run(config: &Config, api: &CommonApi) -> Result<()> {
137136
.saturating_sub(mem_state.zfs_arc_min) as f64;
138137
let mem_avail = mem_avail + zfs_shrinkable_size;
139138

140-
let pagecache = mem_state.pagecache as f64 * 1024.;
141-
let reclaimable = mem_state.s_reclaimable as f64 * 1024.;
142-
let shmem = mem_state.shmem as f64 * 1024.;
139+
let pagecache = mem_state.pagecache as f64;
140+
let reclaimable = mem_state.s_reclaimable as f64;
141+
let shmem = mem_state.shmem as f64;
143142

144143
// See https://lore.kernel.org/lkml/[email protected]/
145144
let cached = pagecache + reclaimable - shmem + zfs_shrinkable_size;
146145

147-
let buffers = mem_state.buffers as f64 * 1024.;
146+
let buffers = mem_state.buffers as f64;
148147

149-
// same logic as htop
150-
let used_diff = mem_free + buffers + pagecache + reclaimable;
151-
let mem_used = if mem_total >= used_diff {
152-
mem_total - used_diff
153-
} else {
154-
mem_total - mem_free
155-
};
148+
// Userspace should use `mem_avail` for estimating the memory that is available.
149+
// See: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773
150+
let mem_used = mem_total - mem_avail;
156151

157152
// account for ZFS ARC cache
158153
let mem_used = mem_used - zfs_shrinkable_size;
159154

160-
let swap_total = mem_state.swap_total as f64 * 1024.;
161-
let swap_free = mem_state.swap_free as f64 * 1024.;
162-
let swap_cached = mem_state.swap_cached as f64 * 1024.;
155+
let swap_total = mem_state.swap_total as f64;
156+
let swap_free = mem_state.swap_free as f64;
157+
let swap_cached = mem_state.swap_cached as f64;
163158
let swap_used = swap_total - swap_free - swap_cached;
164159

165160
// Zswap usage
166-
let zswap_compressed = mem_state.zswap_compressed as f64 * 1024.;
167-
let zswap_decompressed = mem_state.zswap_decompressed as f64 * 1024.;
161+
let zswap_compressed = mem_state.zswap_compressed as f64;
162+
let zswap_decompressed = mem_state.zswap_decompressed as f64;
168163

169164
let zswap_comp_ratio = if zswap_compressed != 0.0 {
170165
zswap_decompressed / zswap_compressed
@@ -310,19 +305,23 @@ impl Memstate {
310305
.and_then(|x| u64::from_str(x).ok())
311306
.error("failed to parse /proc/meminfo")?;
312307

308+
// These values are reported as “kB” but are actually “kiB”.
309+
// Convert them into bytes to avoid having to handle this later.
310+
// Source: https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/6/html/deployment_guide/s2-proc-meminfo#s2-proc-meminfo
311+
const KIB: u64 = 1024;
313312
match name {
314-
"MemTotal:" => mem_state.mem_total = val,
315-
"MemFree:" => mem_state.mem_free = val,
316-
"MemAvailable:" => mem_state.mem_available = val,
317-
"Buffers:" => mem_state.buffers = val,
318-
"Cached:" => mem_state.pagecache = val,
319-
"SReclaimable:" => mem_state.s_reclaimable = val,
320-
"Shmem:" => mem_state.shmem = val,
321-
"SwapTotal:" => mem_state.swap_total = val,
322-
"SwapFree:" => mem_state.swap_free = val,
323-
"SwapCached:" => mem_state.swap_cached = val,
324-
"Zswap:" => mem_state.zswap_compressed = val,
325-
"Zswapped:" => mem_state.zswap_decompressed = val,
313+
"MemTotal:" => mem_state.mem_total = val * KIB,
314+
"MemFree:" => mem_state.mem_free = val * KIB,
315+
"MemAvailable:" => mem_state.mem_available = val * KIB,
316+
"Buffers:" => mem_state.buffers = val * KIB,
317+
"Cached:" => mem_state.pagecache = val * KIB,
318+
"SReclaimable:" => mem_state.s_reclaimable = val * KIB,
319+
"Shmem:" => mem_state.shmem = val * KIB,
320+
"SwapTotal:" => mem_state.swap_total = val * KIB,
321+
"SwapFree:" => mem_state.swap_free = val * KIB,
322+
"SwapCached:" => mem_state.swap_cached = val * KIB,
323+
"Zswap:" => mem_state.zswap_compressed = val * KIB,
324+
"Zswapped:" => mem_state.zswap_decompressed = val * KIB,
326325
_ => (),
327326
}
328327

0 commit comments

Comments
 (0)