Skip to content

serialize: MLX free-buffer pool is unbounded (lane-only cacheLimit) — measured +7.7GB on a long prefill #162

Description

@penta2himajin

Observation

Memory.cacheLimit is bound on the lane path only. From #149's own comment: "Lane-scoped (LaneBackend is only built under QWISP_LANES); the serialize path is untouched." Default QWISP_LANE_MLX_CACHE_MB = 2048.

The default serialize path therefore runs with MLX's free-buffer pool unbounded, and #150 measured what that costs: on a 35,178-token prefill the pool grew +7.7GB (cache 4,845 → 12,523MB), roughly half of the 16GB total footprint growth. Confirmed by the observer effect that hid it: with QWISP_PREFILL_MEMDBG=2 (which calls clearCache() every report) the same prefill peaked ~6GB lower.

Why this is not obviously a win

On lanes, bounding the pool measured −22.5GB peak AND ~10% faster in the crash configuration (#149) — the speed came from relieving memory pressure on a 64GB box. Neither number transfers:

  • serialize holds one request's working set, not B lanes' — the pool may be recycling buffers that a limit would force it to re-allocate, i.e. the same bound could cost time here rather than save it.
  • the +7.7GB was measured on a machine where nothing was under pressure. Whether reclaiming it changes anything depends on the tier, and streaming tiers (where RAM is actually scarce) were not measured at all.

Step 0

Paired A/B on the serialize path, same binary, one long prefill plus a decode run:

  1. QWISP_PREFILL_MLX_CACHE_MB unset (today) vs 2048 vs 512.
  2. Report footprint peak, MLX.Memory active/cache, and tok/s for both prefill and decode — the speed side is the one that decides it, not the memory side.
  3. Repeat at a streaming tier (QWISP_RAW_C low / qwisp simulate), where the memory would actually matter.

Kill criteria, fixed before looking: if bounding costs >2% decode tok/s at resident tier, close — the reclaimed memory is not needed there. If it is speed-neutral AND reclaims >4GB, ship it default-on for the streaming tiers first.

Instruments already exist: QWISP_PREFILL_MEMDBG=1 for the breakdown (mode 2 perturbs — see #150), footprint <pid> (never ps rss).

Refs

#150 (measurement that surfaced this) · #148 / #149 (the lane precedent and its numbers) · TellRuntime.swift Tell.prefill · LaneServe.swift (the lane-scoped MLX.Memory.cacheLimit site)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions