Home / Guides / Troubleshooting / Apple
macOS
Written by Jakub Rusinowski · Last updated September 1, 2026
AI educator & workshop leader on local LLM deployment
Activity Monitor → Memory
Memory Pressure: ▇▇▇▇▇▇▇▇ (red)
Swap Used: 14.62 GB
Memory Used: 31.88 GB of 32.00 GB
| If you see | The cause is | Go to |
|---|---|---|
| Memory Pressure is red and Swap Used is climbing into the gigabytes | The working set exceeds physical memory and macOS is paging to SSD | Fix 2: cut the model or the context |
| Everything freezes and the beachball appears the moment the model loads | A single large allocation pushed the whole system into swap at once | Fix 1: confirm it in Activity Monitor, then Fix 2 |
| It runs fine for a while and degrades as the conversation grows | The KV cache grows with context and is eating the remaining headroom | Fix 3: cap the context length |
| Pressure is yellow and generation is merely slow, not frozen | You are close to the limit but not over it | Fix 4: close the browser and reclaim a few gigabytes |
| Memory is fine and the loader still reports a low working-set size | The Metal working-set ceiling, not memory pressure | This is a different page — see the wired-limit guide |
On an Apple Silicon Mac there is no separate VRAM to run out of, so there is no out-of-memory error to read. The model loads, macOS accepts the allocation, and then the machine becomes unusable — cursor stuttering, beachball, everything slow, generation at a fraction of a token per second.
Apple Silicon shares one pool of memory between CPU and GPU, which is what makes it good at this — no copying weights across a bus — and also what removes the safety net. On a discrete GPU an oversized model fails with an out-of-memory error. Here, macOS does what it always does when memory is short: it swaps, writing least-recently-used pages to SSD. For most applications that is graceful. For inference it is catastrophic, because the working set is the model weights and they are all touched on every single token, so the machine spends its time paging gigabytes back and forth. A model that fits your total memory on paper does not fit in practice, because macOS itself, your browser, and the inference app's own overhead are drawing on the same pool.
Open Activity Monitor → Memory. Two figures matter, and neither is "Memory Used". Memory Pressure is the graph at the bottom: green is healthy, yellow is tight, red means macOS is actively paging. Swap Used should be near zero on a machine with headroom; gigabytes of swap while a model is loaded is the diagnosis. vm_stat gives the same picture in a terminal, and the pageout counts are the ones to watch.
# zsh — swap in use, and how much has been paged out
sysctl vm.swapusage
vm_stat | grep -E 'Pageouts|Swapins|Swapouts'
# Watch memory pressure live while a model generates
memory_pressure -l 1vm.swapusage shows used swap growing while the model runs, and returning to roughly flat once it unloads.sysctl vm.swapusageThe practical rule is that about 70–75% of total unified memory is available to a model, with the rest going to macOS, the window server, and whatever else you have open. That is also the fraction our own calculator uses, so the numbers here and on the analyzer agree. Below, what actually fits at Q4_K_M with an 8K context, computed from the same engine that drives the site — the figures include the KV cache and runtime overhead, not just the weights. 8 GB (~6 GB usable): a 3B (3.7 GB) comfortably, a 4B (4.4 GB) at a squeeze. An 8B at Q4 needs 6.7 GB and will swap. 16 GB (~12 GB usable): an 8B (6.7–7.0 GB) comfortably; a 14B (11.1 GB) fits with little to spare. 24 GB (~18 GB usable): a 14B comfortably; a 24B (16.4 GB) fits. 36 GB (~27 GB usable): a 32B (22.8 GB) or a 27B (25.4 GB), the latter tight. 48 GB (~36 GB usable): a 32B with real headroom, or a 30B MoE. 64 GB (~48 GB usable): a 70B (45.7 GB) fits, with almost nothing spare. 128 GB (~96 GB usable): a 70B comfortably, with room for a long context.
# zsh — your actual total, in GB
sysctl -n hw.memsize | awk '{printf "%.0f GB total, ~%.1f GB usable for a model\n", $1/1073741824, $1/1073741824*0.75}'sysctl vm.swapusage && ollama psThe KV cache grows linearly with context and it comes out of the same pool as the weights. A model that loads comfortably at 4K can push a 16 GB Mac into swap at 32K, which is exactly the pattern behind "it was fine and then got slow as we talked". Ollama's default is 4096 tokens; raising it is a memory decision, not a convenience one. Set it deliberately and measure.
# zsh — cap it for one run and watch what changes
OLLAMA_CONTEXT_LENGTH=4096 ollama run qwen3:8b
# Persist it for the Ollama app
launchctl setenv OLLAMA_CONTEXT_LENGTH 8192
# then quit and reopen the Ollama appsysctl vm.swapusageThis sounds like filler advice and it is not: on most Macs the browser is the largest memory consumer after the model. A Chrome or Safari window with thirty tabs, a video call, and a couple of Electron apps routinely account for 6–10 GB, which on a 16 GB machine is the entire difference between fitting and swapping. Sort Activity Monitor by memory and look at the top of the list before concluding the model is too big.
# zsh — top ten memory consumers right now
ps -A -o rss=,comm= | sort -rn | head -10 | awk '{printf "%.1f GB %s\n", $1/1048576, $2}'memory_pressure -l 1 | tail -3If a model is close but not quite fitting, the cheaper move is a lower quant rather than a smaller model. Q4_K_M is the sweet spot for local use and the quality gap from Q6 or Q8 is small enough that most people cannot identify it in chat, coding, or summarisation. Going below Q4 is where degradation becomes obvious. On a Mac the choice is more consequential than on a discrete GPU, because the penalty for overshooting is swap rather than a clean refusal.
# zsh — a Q4_K_M tag rather than the default
ollama pull qwen3:8b-q4_K_M
ollama run qwen3:8b-q4_K_M
ollama psThere is a separate limit on how much of unified memory Metal will hand the GPU, and raising it is sometimes appropriate — but it is the last thing to try, not the first. It does not create memory; it changes the split, and raising it on a machine that is already swapping makes things worse rather than better. Do it only once Memory Pressure is green at your chosen model size and the loader is still reporting a working-set ceiling below what you have spare.
# zsh — what does Metal currently think it can use?
# Look for this line in llama.cpp / Ollama loader output:
# ggml_metal_init: recommendedMaxWorkingSetSize = ...
journalctl 2>/dev/null || log show --last 5m --predicate 'process CONTAINS "ollama"' | grep -i recommendedMaxIf memory pressure is green and the loader still refuses to allocate, the Metal working-set ceiling is the constraint rather than memory itself. If the GPU is not being used at all — swap or no swap — that is a different failure with its own page.
Include this when you report it
sysctl hw.memsize and sysctl vm.swapusage while the model is loadedBecause unified memory has no separate VRAM to exhaust. macOS accepts the allocation and swaps least-recently-used pages to SSD. Since inference touches every weight on every token, the machine spends its time paging, which presents as a freeze rather than an error.
About 70–75% in practice, with the rest going to macOS, the window server and your other applications. Our calculator uses 75% for exactly this reason, so a 16 GB Mac has roughly 12 GB of headroom for a model plus its KV cache.
Yes, at 3B and below. A 3B at Q4 needs about 3.7 GB with an 8K context, which fits the roughly 6 GB you have available. An 8B at Q4 needs about 6.7 GB and will push an 8 GB machine into swap.
The KV cache grows with context and draws on the same memory pool as the weights. A model comfortable at 4K tokens can push a machine into swap by 32K. Capping the context length fixes it, and it is the same arithmetic as choosing the model size.
No, and it can make it worse. That setting changes how unified memory is split between GPU and system, not how much exists. On a machine already swapping, giving the GPU more takes it from macOS. Get memory pressure green first, then consider it.