From 35b18b2725737d21a7fa97cf37d3db91cdf7aeff Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 10 Jun 2021 14:58:52 +0200 Subject: [PATCH 1/2] Add support for mallinfo2 on glibc Linux --- crates/profile/src/memory_usage.rs | 35 +++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/crates/profile/src/memory_usage.rs b/crates/profile/src/memory_usage.rs index 6ef58c9c14e9..0b0a196aeb72 100644 --- a/crates/profile/src/memory_usage.rs +++ b/crates/profile/src/memory_usage.rs @@ -32,9 +32,7 @@ impl MemoryUsage { allocated: Bytes(jemalloc_ctl::stats::allocated::read().unwrap() as isize), } } else if #[cfg(all(target_os = "linux", target_env = "gnu"))] { - // Note: This is incredibly slow. - let alloc = unsafe { libc::mallinfo() }.uordblks as isize; - MemoryUsage { allocated: Bytes(alloc) } + memusage_linux() } else if #[cfg(windows)] { // There doesn't seem to be an API for determining heap usage, so we try to // approximate that by using the Commit Charge value. @@ -58,6 +56,37 @@ impl MemoryUsage { } } +#[cfg(all(target_os = "linux", target_env = "gnu"))] +fn memusage_linux() -> MemoryUsage { + // Linux/glibc has 2 APIs for allocator introspection that we can use: mallinfo and mallinfo2. + // mallinfo uses `int` fields and cannot handle memory usage exceeding 2 GB. + // mallinfo2 is very recent, so its presence needs to be detected at runtime. + // Both are abysmally slow. + + use std::ffi::CStr; + use std::sync::atomic::{AtomicUsize, Ordering}; + + static MALLINFO2: AtomicUsize = AtomicUsize::new(1); + + let mut mallinfo2 = MALLINFO2.load(Ordering::Relaxed); + if mallinfo2 == 1 { + let cstr = CStr::from_bytes_with_nul(b"mallinfo2\0").unwrap(); + mallinfo2 = unsafe { libc::dlsym(libc::RTLD_DEFAULT, cstr.as_ptr()) } as usize; + // NB: races don't matter here, since they'll always store the same value + MALLINFO2.store(mallinfo2, Ordering::Relaxed); + } + + if mallinfo2 == 0 { + // mallinfo2 does not exist, use mallinfo. + let alloc = unsafe { libc::mallinfo() }.uordblks as isize; + MemoryUsage { allocated: Bytes(alloc) } + } else { + let mallinfo2: fn() -> libc::mallinfo2 = unsafe { std::mem::transmute(mallinfo2) }; + let alloc = mallinfo2().uordblks as isize; + MemoryUsage { allocated: Bytes(alloc) } + } +} + #[derive(Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] pub struct Bytes(isize); From 74dc9bb0e9c1d62b3faa33b204abb04a17e57bcf Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 11 Jun 2021 23:55:27 +0200 Subject: [PATCH 2/2] Update libc --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2bd8897f05cc..bcbf6a342085 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -765,9 +765,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.95" +version = "0.2.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36" +checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6" [[package]] name = "libloading"