Same file. Same bytes. Nearly 6x the RAM.

August 1, 2026 · 9 min read

LFM2.5-350M is a single 355 MB GGUF file. Load it on an iPhone 13 Mini and it costs 56 MB of RAM. Load the identical file, through the identical inference engine, on a Samsung Galaxy A56, and it costs 330 MB — nearly 6x more, from bytes that are byte-for-byte the same on disk. Nothing about the model changed. The operating system underneath it did.

The numbers, once more slowly

These figures come from Cactus Compute's own March 2026 benchmark of their runtime running LFM2.5-350M across real hardware — the same engine on every device, which matters, because it rules out "different software stack" as the explanation:

RAM used to load the identical 355 MB LFM2.5-350M GGUF, same engine, per device (MB) iPhone 13 Mini — 56 MB iPhone 17 Pro — 75 MB Apple Vision Pro — 85 MB Raspberry Pi 5 — 300 MB Galaxy S25 Ultra — 322 MB Pixel 6a — 328 MB Galaxy A56 — 330 MB Green = Apple Silicon / visionOS. Grey = Android + one Linux SBC. File size: 355 MB, identical across every bar. Source: Cactus Compute, "LFM2.5-350M" (cactuscompute.com/blog/lfm2-5-350m), published 2026-03-31

Every green bar is Apple hardware. Every grey bar is Android or a Linux single-board computer. There's effectively no overlap: the tightest Android number (Galaxy S25 Ultra, 322 MB) is still nearly 4x the loosest Apple number (Vision Pro, 85 MB), and the gap between the two closest same-family devices — iPhone 13 Mini at 56 MB versus Galaxy A56 at 330 MB — is 5.9x.

Why: it's not the model, it's mmap

The mechanism, in Cactus's own words: their format uses mmap() to map the GGUF file directly into virtual address space rather than copying it into heap memory. On Apple Silicon, that mapping does what the POSIX spec says it should — "there's no distinction between CPU memory and file cache" — so pages of the model that aren't actively needed for the current token stay as reclaimable file-backed memory the OS can drop and cheaply re-fault, rather than resident, uncollectable RAM. The reported RSS ends up closer to the model's actual working set than to its file size.

Android, per Cactus's account, frequently doesn't honor that same contract:

many Android devices aggressively copy memory-mapped pages into anonymous memory due to SELinux policies and vendor-specific memory management. The result is that mmap() often degrades to something closer to malloc() + read().

Once mapped pages become anonymous memory instead of reclaimable file-backed memory, the OS can no longer treat "not currently needed" as "safe to drop" — the whole file effectively becomes resident, and RSS tracks file size almost 1:1. That's consistent with the numbers: Android RAM figures here cluster tightly around 300–330 MB, a hair under the 355 MB file size, exactly what you'd expect if most of the file ends up copied into memory rather than lazily paged.

This breaks a rule of thumb the whole industry uses — including ours

Every on-device model catalog we know of, privateSLM's included, sizes a "minimum RAM" number as a fixed multiple of file size. Ours is roughly file size × 1.6, rounded up to a device tier (2, 3, 4, or 6 GB). That's a defensible rule if RAM cost is a property of the bytes on disk. The numbers above say it isn't, at least not uniformly — RAM cost is a property of what the OS's virtual memory system does with those bytes once they're mapped, and that can vary by close to 6x for a file that hasn't changed at all.

The practical failure mode cuts both ways. A heuristic tuned by watching mostly-Android telemetry will overestimate how much RAM an Apple-platform build actually needs, rating models "too big" for phones that would run them comfortably. A heuristic tuned by watching mostly-Apple telemetry will do the opposite on Android, shipping "comfortable" ratings onto devices where the same file actually eats most of the phone's free memory. Neither error shows up by inspecting the model. Both only show up by measuring real resident memory, per platform, after load — which is a different and more expensive exercise than multiplying a file size by a constant.

What this means if you build cross-platform

A few concrete takeaways, all downstream of the same point — file size is not RAM cost:

  • Don't reuse one minRamMb number across operating systems. Measure actual RSS after model load on each target platform; don't derive it from the GGUF's byte count.
  • On Android specifically, verify your mmap() calls are actually being honored as lazy, evictable file-backed mappings rather than silently upgraded to anonymous memory — /proc/self/status's VmRSS against the mapped region size is the cheap way to check this per device, not an assumption you can make once and reuse.
  • Treat "supports mmap" in a runtime's feature list as necessary, not sufficient. The runtime calling mmap() doesn't guarantee the kernel underneath treats the mapping the way the runtime author assumed it would.

The honest question this raises for us

privateSLM is iOS/macOS-only, so we don't have to solve the Android side of this. But our own catalog's minRamMb field — in both models.json and the app's ModelInfo struct — is computed with the same generic file-size-times-a-constant heuristic the rest of the industry uses, not measured as real per-model, per-device RSS. Apple's mmap efficiency is probably why our device-fit check's "tight" tier (within 2 GB of the stated minimum, in DeviceInfo.swift) rarely causes real crashes in practice. "Probably" is doing real work in that sentence: we haven't instrumented actual resident memory against our own minRamMb numbers to check whether older, smaller-RAM iPhones are being rated "too big" for models that would in fact run fine. That's a measurement we should run, not a fix we're claiming to have made today.

Today's digest has a smaller, more literal version of the same memory-tiering idea, at a completely different scale — a 28.9M-parameter model that keeps most of its weights out of fast memory on purpose. Worth reading back to back.

Discuss this on the forum → — if you've measured real RSS for the same GGUF across iOS and Android, we'd genuinely like the numbers.