33 lines
1.4 KiB
Rust
33 lines
1.4 KiB
Rust
//! Give memory the system allocator keeps after frees back to the system
|
|
//! ([`lightcraft_engine::memory::set_release_hook`]).
|
|
//!
|
|
//! macOS's allocator keeps freed large blocks mapped as "reusable": they no longer count in the
|
|
//! process's memory footprint but stay in its resident size until the system runs short. After a
|
|
//! raw decode (hundreds of MB of temporaries) that made the resident size climb towards the sum of
|
|
//! everything ever decoded. `malloc_zone_pressure_relief` (libSystem) returns those pages now.
|
|
//! Elsewhere (glibc, Windows) blocks this large are unmapped when freed: nothing to do.
|
|
|
|
/// Install the hook for this platform.
|
|
pub fn install() {
|
|
#[cfg(target_os = "macos")]
|
|
lightcraft_engine::memory::set_release_hook(macos::release);
|
|
}
|
|
|
|
#[cfg(target_os = "macos")]
|
|
#[allow(unsafe_code)]
|
|
mod macos {
|
|
unsafe extern "C" {
|
|
/// libSystem malloc: release free memory of `zone` (all zones when null) back to the
|
|
/// system, up to `goal` bytes (0 = as much as possible). Returns the bytes released.
|
|
fn malloc_zone_pressure_relief(zone: *mut std::ffi::c_void, goal: usize) -> usize;
|
|
}
|
|
|
|
pub fn release() {
|
|
// SAFETY: a documented libSystem function taking a null zone (= every zone) and a size;
|
|
// it only returns free pages to the system and touches no memory we own.
|
|
unsafe {
|
|
malloc_zone_pressure_relief(std::ptr::null_mut(), 0);
|
|
}
|
|
}
|
|
}
|