Files
lightcraft/apps/lightcraft-cli/src/alloc_release.rs
T
Brandon ThomasandClaude Opus 5.5 7266f4153f M5.6c: one memory budget for caches, decode gate and GPU pool; peak RSS 1.9-2.3 GB -> 0.83-0.99 GB
- 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>
2026-10-01 11:35:08 -04:00

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);
}
}
}