Skip to main content

rustfs_mimalloc/
api.rs

1//! Stats, options, version, and process information APIs.
2
3use crate::MiMalloc;
4use core::ffi::c_void;
5
6/// Process memory information returned by [`MiMalloc::process_info`].
7#[derive(Debug, Clone, Copy, Default)]
8pub struct ProcessInfo {
9    pub elapsed_msecs: usize,
10    pub user_msecs: usize,
11    pub system_msecs: usize,
12    pub current_rss: usize,
13    pub peak_rss: usize,
14    pub current_commit: usize,
15    pub peak_commit: usize,
16    pub page_faults: usize,
17}
18
19impl MiMalloc {
20    /// mimalloc version as `major * 10000 + minor * 100 + patch`.
21    #[inline]
22    pub fn version() -> i32 {
23        unsafe { rustfs_mimalloc_sys::mi_version() }
24    }
25
26    /// Force garbage collection.
27    #[inline]
28    pub fn collect(force: bool) {
29        unsafe { rustfs_mimalloc_sys::mi_collect(force) }
30    }
31
32    /// Usable size of an allocated block (may be larger than requested).
33    ///
34    /// # Safety
35    /// `ptr` must have been allocated by mimalloc.
36    #[inline]
37    pub unsafe fn usable_size(ptr: *const u8) -> usize {
38        unsafe { rustfs_mimalloc_sys::mi_usable_size(ptr as *const c_void) }
39    }
40
41    /// Process memory information.
42    pub fn process_info() -> ProcessInfo {
43        let mut info = ProcessInfo::default();
44        unsafe {
45            rustfs_mimalloc_sys::mi_process_info(
46                &mut info.elapsed_msecs,
47                &mut info.user_msecs,
48                &mut info.system_msecs,
49                &mut info.current_rss,
50                &mut info.peak_rss,
51                &mut info.current_commit,
52                &mut info.peak_commit,
53                &mut info.page_faults,
54            );
55        }
56        info
57    }
58
59    // ── Stats ───────────────────────────────────────────────────────────────
60
61    /// Allocation statistics as JSON. Returns empty string on failure.
62    pub fn stats_json() -> String {
63        unsafe {
64            crate::ffi::owned_mimalloc_string(rustfs_mimalloc_sys::mi_stats_get_json(
65                0,
66                core::ptr::null_mut(),
67            ))
68        }
69    }
70
71    /// Allocation statistics in mimalloc's human-readable text format.
72    pub fn stats_print() -> String {
73        crate::ffi::collect_mimalloc_output(|out, arg| unsafe {
74            rustfs_mimalloc_sys::mi_stats_print_out(out, arg);
75        })
76    }
77
78    /// Reset accumulated mimalloc allocation statistics.
79    #[inline]
80    pub fn stats_reset() {
81        unsafe { rustfs_mimalloc_sys::mi_stats_reset() }
82    }
83
84    /// Process memory information in mimalloc's human-readable text format.
85    pub fn process_info_print() -> String {
86        crate::ffi::collect_mimalloc_output(|out, arg| unsafe {
87            rustfs_mimalloc_sys::mi_process_info_print_out(out, arg);
88        })
89    }
90
91    // ── Options ─────────────────────────────────────────────────────────────
92
93    /// Check if an option is enabled.
94    #[inline]
95    pub fn option_is_enabled(option: rustfs_mimalloc_sys::mi_option_t) -> bool {
96        unsafe { rustfs_mimalloc_sys::mi_option_is_enabled(option) }
97    }
98
99    /// Get an option value.
100    #[inline]
101    pub fn option_get(option: rustfs_mimalloc_sys::mi_option_t) -> rustfs_mimalloc_sys::c_long {
102        unsafe { rustfs_mimalloc_sys::mi_option_get(option) }
103    }
104
105    /// Get an option value as size (bytes).
106    #[inline]
107    pub fn option_get_size(option: rustfs_mimalloc_sys::mi_option_t) -> usize {
108        unsafe { rustfs_mimalloc_sys::mi_option_get_size(option) }
109    }
110
111    /// Set an option value.
112    ///
113    /// ```rust
114    /// use rustfs_mimalloc::MiMalloc;
115    /// use rustfs_mimalloc_sys::mi_option_t;
116    ///
117    /// // Return memory to OS immediately
118    /// MiMalloc::option_set(mi_option_t::mi_option_purge_delay, 0);
119    /// ```
120    #[inline]
121    pub fn option_set(
122        option: rustfs_mimalloc_sys::mi_option_t,
123        value: rustfs_mimalloc_sys::c_long,
124    ) {
125        unsafe { rustfs_mimalloc_sys::mi_option_set(option, value) }
126    }
127
128    /// Enable an option.
129    #[inline]
130    pub fn option_enable(option: rustfs_mimalloc_sys::mi_option_t) {
131        unsafe { rustfs_mimalloc_sys::mi_option_enable(option) }
132    }
133
134    /// Disable an option.
135    #[inline]
136    pub fn option_disable(option: rustfs_mimalloc_sys::mi_option_t) {
137        unsafe { rustfs_mimalloc_sys::mi_option_disable(option) }
138    }
139}
140
141// ── Tests ───────────────────────────────────────────────────────────────────
142
143#[cfg(test)]
144mod tests {
145    use super::*;
146    use rustfs_mimalloc_sys::mi_option_t;
147
148    #[test]
149    fn version_is_v3() {
150        assert!(MiMalloc::version() >= 30500, "expected >= V3.5.0");
151    }
152
153    #[test]
154    fn stats_json_not_empty() {
155        let json = MiMalloc::stats_json();
156        assert!(!json.is_empty());
157    }
158
159    #[test]
160    fn stats_print_not_empty() {
161        let stats = MiMalloc::stats_print();
162        assert!(!stats.is_empty());
163    }
164
165    #[test]
166    fn stats_reset_smoke() {
167        MiMalloc::stats_reset();
168    }
169
170    #[test]
171    fn process_info_print_not_empty() {
172        let info = MiMalloc::process_info_print();
173        assert!(!info.is_empty());
174    }
175
176    #[test]
177    fn option_roundtrip() {
178        // Just verify no panic
179        let _ = MiMalloc::option_get(mi_option_t::mi_option_purge_delay);
180        let _ = MiMalloc::option_is_enabled(mi_option_t::mi_option_show_errors);
181    }
182
183    #[test]
184    fn process_info_smoke() {
185        let info = MiMalloc::process_info();
186        let _ = info;
187    }
188
189    #[test]
190    fn usable_size_at_least_requested() {
191        unsafe {
192            let ptr = rustfs_mimalloc_sys::mi_malloc(64);
193            assert!(MiMalloc::usable_size(ptr as *const u8) >= 64);
194            rustfs_mimalloc_sys::mi_free(ptr);
195        }
196    }
197}