Setup: MacBook Pro M5 Max 64 GB · macOS 26.5.2 · Vpipe Manager v0.1.23 (CLI helper) · MiniMax-H3 FL2VA upstream BF16 DiT + BF16 text encoder (local diffusers layout, unregistered, probed fine) · larryvrh Turbo v4-600 runtime LoRA · 544×960 · 124 frames · steps=4.
Log (works as designed, clip comes out fine):
MiniMax-H3 DiT 0 of 50 blocks pinned at load (none fit beside the other models;
the resident set grows into free RAM as the denoise runs)
DiT residency ended at 50 of 50 blocks (61566 MB), 0 pinned at load
Activity Monitor at the same moment:
- Memory used 45.39 GB + cached files 18.54 GB = 63.93 ≈ 64.00 (RAM completely full)
- App 3.41 GB · wired 7.95 GB · compressed 33.08 GB · swap used 28.74 GB
- compressed + swap ≈ 62 GB ≈ the entire BF16 DiT
So the 50/50 "resident" set is not physically resident: macOS moved most of it into the compressor pool and swap, and the per-step sequential scan re-inflates the blocks in order, every step — hidden streaming through the swapfile instead of the checkpoint.
Why admission gets fooled (hypothesis, from the residency notes in metal-minimax-h3-transformer.h): admission checks system free headroom, and macOS keeps manufacturing "free" RAM by compressing the very blocks the DiT admitted earlier. The ratchet never fires because OS-side eviction is invisible to the process — the blocks still look resident. On 16 GB the gap is so large that growth stops early; a ~62 GB model on a 64 GB box sits exactly in the regime where the loop can run to 100%.
Impact
- ~29 GB of swap writes per clip (the DiT is dropped after each clip, so every generation re-grows and re-spills) — real SSD wear for anyone generating many clips a day
- ~10–15 s/step of decompress + swap-in tax
- the rest of the machine is squeezed out while the run lasts
Suggestion: an env override for the residency reserve, e.g.
std::size_t reserve = need + (1ull << 30);
if (const char* e = std::getenv("VPIPE_H3_RESERVE_GB")) {
const std::size_t want = (std::size_t)(std::atof(e) * 1073741824.0);
if (want > reserve) reserve = want;
}
_h3_dit->set_residency_reserve(reserve);
VPIPE_H3_RESERVE_GB=22 on this box should stop growth around ~25 blocks and stream the rest from the checkpoint (clean file reads, zero swap). Alternatively, admission could compare the process's own phys_footprint against physical RAM instead of trusting system free memory.
Update — measured with the patch applied (same box, same clip spec, VPIPE_H3_RESERVE_GB=22):
|
stock v0.1.23 |
patched (22 GB reserve) |
| residency ended at |
50 of 50 (61,566 MB) |
21 of 50 (25,857 MB) |
| swap growth during run |
~29 GB |
none |
| steps (4 NFE, 544×960×124f) |
— |
94.1 / 67.8 / 70.6 / 71.6 s |
| end-to-end |
~12–15 min |
6 min 30 s |
Capping the growth didn't just stop the swap — it more than halved the wall time. The hidden per-step tax of re-inflating the over-grown set through the compressor/swap was far larger than the honest streaming reads it replaced.
I'm testing a locally patched build with exactly this change and can report numbers (residency count, step time, swap) if useful. Thanks for the project — everything else (probe-the-checkpoint detection on an unregistered diffusers layout, runtime LoRA, BF16 encoder streaming) worked out of the box.
A working patch (with the measurements above) is ready to cherry-pick:
https://github.com/skymars13/vpipe/tree/reserve-env-cap — commit 74cceca, one file, default behavior unchanged (the env only ever raises the reserve).
PR creation on this repo is limited to collaborators, so filing as an issue instead — happy to open a PR if you enable it, or just take the commit.
Setup: MacBook Pro M5 Max 64 GB · macOS 26.5.2 · Vpipe Manager v0.1.23 (CLI helper) · MiniMax-H3 FL2VA upstream BF16 DiT + BF16 text encoder (local diffusers layout, unregistered, probed fine) · larryvrh Turbo v4-600 runtime LoRA · 544×960 · 124 frames · steps=4.
Log (works as designed, clip comes out fine):
Activity Monitor at the same moment:
So the 50/50 "resident" set is not physically resident: macOS moved most of it into the compressor pool and swap, and the per-step sequential scan re-inflates the blocks in order, every step — hidden streaming through the swapfile instead of the checkpoint.
Why admission gets fooled (hypothesis, from the residency notes in metal-minimax-h3-transformer.h): admission checks system free headroom, and macOS keeps manufacturing "free" RAM by compressing the very blocks the DiT admitted earlier. The ratchet never fires because OS-side eviction is invisible to the process — the blocks still look resident. On 16 GB the gap is so large that growth stops early; a ~62 GB model on a 64 GB box sits exactly in the regime where the loop can run to 100%.
Impact
Suggestion: an env override for the residency reserve, e.g.
VPIPE_H3_RESERVE_GB=22on this box should stop growth around ~25 blocks and stream the rest from the checkpoint (clean file reads, zero swap). Alternatively, admission could compare the process's own phys_footprint against physical RAM instead of trusting system free memory.Update — measured with the patch applied (same box, same clip spec,
VPIPE_H3_RESERVE_GB=22):Capping the growth didn't just stop the swap — it more than halved the wall time. The hidden per-step tax of re-inflating the over-grown set through the compressor/swap was far larger than the honest streaming reads it replaced.
I'm testing a locally patched build with exactly this change and can report numbers (residency count, step time, swap) if useful. Thanks for the project — everything else (probe-the-checkpoint detection on an unregistered diffusers layout, runtime LoRA, BF16 encoder streaming) worked out of the box.
A working patch (with the measurements above) is ready to cherry-pick:
https://github.com/skymars13/vpipe/tree/reserve-env-cap — commit
74cceca, one file, default behavior unchanged (the env only ever raises the reserve).PR creation on this repo is limited to collaborators, so filing as an issue instead — happy to open a PR if you enable it, or just take the commit.