mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-23 12:12:53 -05:00
- memory::budget (default min(25% RAM, 1.5 GiB); LIGHTCRAFT_MEMORY_MB, app.memoryBudget): half for engine caches (sources + rendered previews, LRU across them via a global use tick; the photo on screen stays), a quarter for decodes in flight (WorkGate: thumbnails, prefetch and import probes wait; loupe/export loads never wait), an eighth for the GPU free pool. - GPU: best-fit buffer reuse (<= 25% slack), buffers released outside a render are pooled at once (no stranded retired lists), pool trimmed after 3 s idle. - Decodes drop file bytes and raw samples early, colour/crop/orient in place. - macOS: apps install malloc_zone_pressure_relief as the release hook (after each decode, import and idle trim): freed large blocks no longer stay resident. 14 raws + loupe + 12 steps (M4 Pro): peak RSS 1.9-2.3 GB -> 0.83-0.99 GB, footprint 2.5-2.6 GB -> 0.91-0.96 GB, heap peak 930 -> 656 MB; stepping median ~13 ms. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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);
|
|
}
|
|
}
|
|
}
|