Skip to content

Commit b39573c

Browse files
authored
Merge pull request #3 from Arc-blroth/feat/always_use_statm
add always_use_statm feature
2 parents 5364d0d + 4eba8db commit b39573c

File tree

3 files changed

+48
-28
lines changed

3 files changed

+48
-28
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "memory-stats"
33
authors = ["Arc-blroth <[email protected]>"]
44
license = "MIT OR Apache-2.0"
5-
version = "1.0.0"
5+
version = "1.1.0"
66
edition = "2021"
77
description = "A cross-platform memory profiler for Rust."
88
repository = "https://github.com/Arc-blroth/memory-stats"
@@ -18,3 +18,7 @@ winapi = { version = "0.3.9", features = ["minwindef", "processthreadsapi", "psa
1818

1919
[target.'cfg(any(target_os = "linux", target_os = "android", target_os = "macos", target_os = "ios"))'.dependencies]
2020
libc = "0.2"
21+
22+
[features]
23+
# Always use the faster but less accurate /proc/self/statm statistics on Linux.
24+
always_use_statm = []

src/linux.rs

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
33

44
use crate::MemoryStats;
55

6+
#[cfg(not(feature = "always_use_statm"))]
67
const SMAPS: &str = "/proc/self/smaps";
78
const STATM: &str = "/proc/self/statm";
89

10+
#[cfg(not(feature = "always_use_statm"))]
911
static SMAPS_CHECKED: AtomicBool = AtomicBool::new(false);
12+
#[cfg(not(feature = "always_use_statm"))]
1013
static SMAPS_EXIST: AtomicBool = AtomicBool::new(false);
1114
static PAGE_SIZE: AtomicUsize = AtomicUsize::new(0);
1215

@@ -16,25 +19,24 @@ pub fn memory_stats() -> Option<MemoryStats> {
1619
// kernels. We use the inaccurate /proc/self/statm stats
1720
// as a fallback in case smaps isn't avaliable.
1821

22+
#[cfg(feature = "always_use_statm")]
23+
load_page_size()?;
24+
25+
#[cfg(not(feature = "always_use_statm"))]
1926
if let Ok(false) = SMAPS_CHECKED.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed) {
2027
let smaps_exist = fs::metadata(SMAPS).is_ok();
2128

22-
if !smaps_exist && PAGE_SIZE.load(Ordering::Relaxed) == 0 {
23-
let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) };
24-
if page_size == -1 {
25-
// sysconf returned error
26-
return None;
27-
} else {
28-
PAGE_SIZE.store(page_size as usize, Ordering::Relaxed);
29-
}
29+
if !smaps_exist {
30+
load_page_size()?;
3031
}
3132

3233
// store SMAPS_EXIST last to prevent code from loading a PAGE_SIZE of 0
3334
SMAPS_EXIST.store(smaps_exist, Ordering::Relaxed);
3435
}
3536

37+
#[cfg(not(feature = "always_use_statm"))]
3638
if SMAPS_EXIST.load(Ordering::Relaxed) {
37-
match fs::read_to_string(SMAPS) {
39+
return match fs::read_to_string(SMAPS) {
3840
Ok(smap_info) => {
3941
// smaps returns a list of different areas of memory
4042
// and the sizes of each, in kB. smaps_rollup doesn't
@@ -60,25 +62,39 @@ pub fn memory_stats() -> Option<MemoryStats> {
6062
})
6163
}
6264
Err(_) => None,
65+
};
66+
}
67+
68+
match fs::read_to_string(STATM) {
69+
Ok(statm_info) => {
70+
// statm returns the virtual size and rss, in
71+
// multiples of the page size, as the first
72+
// two columns of output.
73+
74+
let page_size = PAGE_SIZE.load(Ordering::Relaxed);
75+
let (total_size_pages, idx) = scan_int(&statm_info);
76+
let (total_rss_pages, _) = scan_int(&statm_info[idx..]);
77+
Some(MemoryStats {
78+
physical_mem: total_rss_pages * page_size,
79+
virtual_mem: total_size_pages * page_size,
80+
})
6381
}
64-
} else {
65-
match fs::read_to_string(STATM) {
66-
Ok(statm_info) => {
67-
// statm returns the virtual size and rss, in
68-
// multiples of the page size, as the first
69-
// two columns of output.
70-
71-
let page_size = PAGE_SIZE.load(Ordering::Relaxed);
72-
let (total_size_pages, idx) = scan_int(&statm_info);
73-
let (total_rss_pages, _) = scan_int(&statm_info[idx..]);
74-
Some(MemoryStats {
75-
physical_mem: total_rss_pages * page_size,
76-
virtual_mem: total_size_pages * page_size,
77-
})
78-
}
79-
Err(_) => None,
82+
Err(_) => None,
83+
}
84+
}
85+
86+
/// Grabs the value of the SC_PAGESIZE if needed.
87+
fn load_page_size() -> Option<()> {
88+
if PAGE_SIZE.load(Ordering::Relaxed) == 0 {
89+
let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) };
90+
if page_size == -1 {
91+
// sysconf returned error
92+
return None;
93+
} else {
94+
PAGE_SIZE.store(page_size as usize, Ordering::Relaxed);
8095
}
8196
}
97+
Some(())
8298
}
8399

84100
/// Extracts a positive integer from a string that
@@ -94,7 +110,7 @@ fn scan_int(string: &str) -> (usize, usize) {
94110
}
95111
for n in chars {
96112
idx += 1;
97-
if ('0'..='9').contains(&n) {
113+
if n.is_ascii_digit() {
98114
out *= 10;
99115
out += n as usize - '0' as usize;
100116
} else {

0 commit comments

Comments
 (0)