Query jemalloc for current system memory statistics. Returns `None` if jemalloc introspection is unavailable (including on wasm32 where the standard allocator is used instead of jemalloc).
()
| 46 | /// Returns `None` if jemalloc introspection is unavailable (including on |
| 47 | /// wasm32 where the standard allocator is used instead of jemalloc). |
| 48 | pub fn query() -> Option<Self> { |
| 49 | #[cfg(not(target_arch = "wasm32"))] |
| 50 | { |
| 51 | // Trigger a stats epoch refresh. |
| 52 | let _ = tikv_jemalloc_ctl::epoch::advance(); |
| 53 | |
| 54 | let allocated = tikv_jemalloc_ctl::stats::allocated::read().ok()?; |
| 55 | let active = tikv_jemalloc_ctl::stats::active::read().ok()?; |
| 56 | let mapped = tikv_jemalloc_ctl::stats::mapped::read().ok()?; |
| 57 | let retained = tikv_jemalloc_ctl::stats::retained::read().ok()?; |
| 58 | let resident = tikv_jemalloc_ctl::stats::resident::read().ok()?; |
| 59 | |
| 60 | // Fragmentation: how much of jemalloc's active memory is wasted. |
| 61 | // active = pages the allocator has obtained from the OS. |
| 62 | // allocated = bytes the application is actually using. |
| 63 | // The difference is internal fragmentation + free-list overhead. |
| 64 | let fragmentation_ratio = if active > 0 { |
| 65 | (active.saturating_sub(allocated)) as f64 / active as f64 |
| 66 | } else { |
| 67 | 0.0 |
| 68 | }; |
| 69 | |
| 70 | Some(Self { |
| 71 | rss_bytes: resident, |
| 72 | allocated_bytes: allocated, |
| 73 | active_bytes: active, |
| 74 | mapped_bytes: mapped, |
| 75 | retained_bytes: retained, |
| 76 | fragmentation_ratio, |
| 77 | }) |
| 78 | } |
| 79 | #[cfg(target_arch = "wasm32")] |
| 80 | { |
| 81 | // wasm32 uses the standard allocator; jemalloc introspection is unavailable. |
| 82 | None |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | /// Returns `true` if fragmentation exceeds the warning threshold (25%). |
| 87 | pub fn is_fragmentation_critical(&self) -> bool { |