use crate::MiMalloc;
use core::ffi::c_void;
#[derive(Debug, Clone, Copy, Default)]
pub struct ProcessInfo {
pub elapsed_msecs: usize,
pub user_msecs: usize,
pub system_msecs: usize,
pub current_rss: usize,
pub peak_rss: usize,
pub current_commit: usize,
pub peak_commit: usize,
pub page_faults: usize,
}
impl MiMalloc {
#[inline]
pub fn version() -> i32 {
unsafe { rustfs_mimalloc_sys::mi_version() }
}
#[inline]
pub fn collect(force: bool) {
unsafe { rustfs_mimalloc_sys::mi_collect(force) }
}
#[inline]
pub unsafe fn usable_size(ptr: *const u8) -> usize {
unsafe { rustfs_mimalloc_sys::mi_usable_size(ptr as *const c_void) }
}
pub fn process_info() -> ProcessInfo {
let mut info = ProcessInfo::default();
unsafe {
rustfs_mimalloc_sys::mi_process_info(
&mut info.elapsed_msecs,
&mut info.user_msecs,
&mut info.system_msecs,
&mut info.current_rss,
&mut info.peak_rss,
&mut info.current_commit,
&mut info.peak_commit,
&mut info.page_faults,
);
}
info
}
pub fn stats_json() -> String {
unsafe {
crate::ffi::owned_mimalloc_string(rustfs_mimalloc_sys::mi_stats_get_json(
0,
core::ptr::null_mut(),
))
}
}
pub fn stats_print() -> String {
crate::ffi::collect_mimalloc_output(|out, arg| unsafe {
rustfs_mimalloc_sys::mi_stats_print_out(out, arg);
})
}
#[inline]
pub fn stats_reset() {
unsafe { rustfs_mimalloc_sys::mi_stats_reset() }
}
pub fn process_info_print() -> String {
crate::ffi::collect_mimalloc_output(|out, arg| unsafe {
rustfs_mimalloc_sys::mi_process_info_print_out(out, arg);
})
}
#[inline]
pub fn option_is_enabled(option: rustfs_mimalloc_sys::mi_option_t) -> bool {
unsafe { rustfs_mimalloc_sys::mi_option_is_enabled(option) }
}
#[inline]
pub fn option_get(option: rustfs_mimalloc_sys::mi_option_t) -> rustfs_mimalloc_sys::c_long {
unsafe { rustfs_mimalloc_sys::mi_option_get(option) }
}
#[inline]
pub fn option_get_size(option: rustfs_mimalloc_sys::mi_option_t) -> usize {
unsafe { rustfs_mimalloc_sys::mi_option_get_size(option) }
}
#[inline]
pub fn option_set(
option: rustfs_mimalloc_sys::mi_option_t,
value: rustfs_mimalloc_sys::c_long,
) {
unsafe { rustfs_mimalloc_sys::mi_option_set(option, value) }
}
#[inline]
pub fn option_enable(option: rustfs_mimalloc_sys::mi_option_t) {
unsafe { rustfs_mimalloc_sys::mi_option_enable(option) }
}
#[inline]
pub fn option_disable(option: rustfs_mimalloc_sys::mi_option_t) {
unsafe { rustfs_mimalloc_sys::mi_option_disable(option) }
}
}
#[cfg(test)]
mod tests {
use super::*;
use rustfs_mimalloc_sys::mi_option_t;
#[test]
fn version_is_v3() {
assert!(MiMalloc::version() >= 30500, "expected >= V3.5.0");
}
#[test]
fn stats_json_not_empty() {
let json = MiMalloc::stats_json();
assert!(!json.is_empty());
}
#[test]
fn stats_print_not_empty() {
let stats = MiMalloc::stats_print();
assert!(!stats.is_empty());
}
#[test]
fn stats_reset_smoke() {
MiMalloc::stats_reset();
}
#[test]
fn process_info_print_not_empty() {
let info = MiMalloc::process_info_print();
assert!(!info.is_empty());
}
#[test]
fn option_roundtrip() {
let _ = MiMalloc::option_get(mi_option_t::mi_option_purge_delay);
let _ = MiMalloc::option_is_enabled(mi_option_t::mi_option_show_errors);
}
#[test]
fn process_info_smoke() {
let info = MiMalloc::process_info();
let _ = info;
}
#[test]
fn usable_size_at_least_requested() {
unsafe {
let ptr = rustfs_mimalloc_sys::mi_malloc(64);
assert!(MiMalloc::usable_size(ptr as *const u8) >= 64);
rustfs_mimalloc_sys::mi_free(ptr);
}
}
}