diff --git a/libmimalloc-sys/src/extended.rs b/libmimalloc-sys/src/extended.rs index d37adba..2d60c48 100644 --- a/libmimalloc-sys/src/extended.rs +++ b/libmimalloc-sys/src/extended.rs @@ -447,6 +447,12 @@ extern "C" { /// /// Note: This function is thread safe. pub fn mi_register_error(out: mi_error_fun, arg: *mut c_void); + + /// Get the statistics for the current subprocess aggregated over all its heaps as JSON. + /// + /// Returns pointer to the buffer or NULL on failure. Use mi_free() to free the buffer if the buf parameter was NULL. + #[cfg(not(feature = "v2"))] + pub fn mi_stats_get_json(buf_size: usize, buf: *mut c_char) -> *mut c_char; } /// An output callback. Must be thread-safe. @@ -1092,7 +1098,7 @@ mod tests { #[test] fn it_calculates_usable_size() { - let ptr = unsafe { mi_malloc(32) } as *mut u8; + let ptr = unsafe { crate::mi_malloc(32) } as *mut u8; let usable_size = unsafe { mi_usable_size(ptr as *mut c_void) }; assert!( usable_size >= 32, diff --git a/src/extended.rs b/src/extended.rs index be9614c..6861dde 100644 --- a/src/extended.rs +++ b/src/extended.rs @@ -1,5 +1,7 @@ use crate::MiMalloc; use core::ffi::c_void; +#[cfg(not(feature = "v2"))] +use core::ffi::{c_char, CStr}; impl MiMalloc { /// Get the mimalloc version. @@ -17,6 +19,29 @@ impl MiMalloc { pub unsafe fn usable_size(&self, ptr: *const u8) -> usize { ffi::mi_usable_size(ptr as *const c_void) } + + /// Call the given function with a string version of the JSON stats for the whole process + /// + /// Allocates (using mimalloc itself) to store the JSON structure. + #[cfg(not(feature = "v2"))] + pub fn with_stats_json(f: F) -> Result + where + F: FnOnce(&str) -> O, + { + unsafe { + let buf = ffi::mi_stats_get_json(0, core::ptr::null::() as *mut _); + if buf.is_null() { + return Err("failed to call mi_stats_get_json"); + } + let cstr = CStr::from_ptr(buf); + let slice = cstr + .to_str() + .map_err(|_| "mi_stats_get_json contained invalid UTF-8")?; + let o = f(slice); + ffi::mi_free(buf as _); + Ok(o) + } + } } #[cfg(test)] @@ -43,4 +68,12 @@ mod test { assert!(usable_size >= 8); } } + + #[test] + #[cfg(not(feature = "v2"))] + fn test_with_stats_json() { + let (first_char, len) = MiMalloc::with_stats_json(|f| (f.chars().next(), f.len())).unwrap(); + assert_eq!(first_char, Some('{')); + assert!(len > 1); + } }