blob: 117ca959df1ad52fbd4f84cbe55fecbc2a12de9f [file] [log] [blame] [edit]
// Copyright 2024 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use std::fs::File;
use std::io;
use std::io::BufRead;
use std::io::BufReader;
/// Struct to hold parsed /proc/meminfo data, only contains used fields.
#[derive(Default, Clone)]
pub struct MemInfo {
pub total: u64,
pub free: u64,
pub active_anon: u64,
pub inactive_anon: u64,
pub active_file: u64,
pub inactive_file: u64,
pub dirty: u64,
pub swap_free: u64,
pub swap_total: u64,
}
impl MemInfo {
/// Load /proc/meminfo and parse it.
pub fn load() -> io::Result<Self> {
let reader = File::open("/proc/meminfo")?;
let reader = BufReader::new(reader);
Self::parse(reader)
}
fn parse<R: BufRead>(reader: R) -> io::Result<Self> {
let mut result = Self::default();
for line in reader.lines() {
let line = line?;
let mut tokens = line.split_whitespace();
let Some(key) = tokens.next() else {
continue;
};
let field = match key {
"MemTotal:" => &mut result.total,
"MemFree:" => &mut result.free,
"Active(anon):" => &mut result.active_anon,
"Inactive(anon):" => &mut result.inactive_anon,
"Active(file):" => &mut result.active_file,
"Inactive(file):" => &mut result.inactive_file,
"Dirty:" => &mut result.dirty,
"SwapFree:" => &mut result.swap_free,
"SwapTotal:" => &mut result.swap_total,
_ => continue,
};
let Some(value) = tokens.next() else {
continue;
};
let Ok(value) = value.parse::<u64>() else {
continue;
};
*field = value;
}
Ok(result)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_meminfo() {
let mock_meminfo = r#"
MemTotal: 8025656 kB
MemFree: 4586928 kB
MemAvailable: 6704404 kB
Buffers: 659640 kB
Cached: 1949056 kB
SwapCached: 0 kB
Active: 1430416 kB
Inactive: 1556968 kB
Active(anon): 489640 kB
Inactive(anon): 29188 kB
Active(file): 940776 kB
Inactive(file): 1527780 kB
Unevictable: 151128 kB
Mlocked: 41008 kB
SwapTotal: 11756332 kB
SwapFree: 11756331 kB
Dirty: 5712 kB
Writeback: 0 kB
AnonPages: 529800 kB
Mapped: 321468 kB
Shmem: 140156 kB
Slab: 169252 kB
SReclaimable: 115540 kB
SUnreclaim: 53712 kB
KernelStack: 7072 kB
PageTables: 13340 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 15769160 kB
Committed_AS: 2483600 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 0 kB
VmallocChunk: 0 kB
Percpu: 2464 kB
AnonHugePages: 40960 kB
ShmemHugePages: 0 kB
ShmemPmdMapped: 0 kB
DirectMap4k: 170216 kB
DirectMap2M: 5992448 kB
DirectMap1G: 3145728 kB"#;
let meminfo = MemInfo::parse(mock_meminfo.as_bytes()).unwrap();
assert_eq!(meminfo.free, 4586928);
assert_eq!(meminfo.active_anon, 489640);
assert_eq!(meminfo.inactive_anon, 29188);
assert_eq!(meminfo.active_file, 940776);
assert_eq!(meminfo.inactive_file, 1527780);
assert_eq!(meminfo.dirty, 5712);
assert_eq!(meminfo.swap_free, 11756331);
assert_eq!(meminfo.swap_total, 11756332);
}
}