Ollama Slow on Mac? Check Loading, Context and Memory
Ollama can be slow because a model is still loading, a prompt has a large context, part of the model is running on the CPU, or the Mac is under memory pressure. Those cases need different changes. Deleting downloaded models can free disk space, but it does not automatically make the model currently generating an answer faster.
Compare cold loading with a second request
Keep the model, prompt and settings the same. Run a short request, then repeat it while the model remains loaded. If only the first request is slow, loading is a useful lead. If both generate slowly, investigate execution and memory. Record the comparison rather than treating one response as a benchmark.
Ollama's API documentation exposes separate timing fields such as load_duration, prompt_eval_duration and eval_duration in completed responses. These distinguish loading, reading the prompt and generating output. Do not compare token rates from different models, context sizes or prompts as though they measured one change.
Measure one local request by stage
For a local server on the usual port, the following request makes the timing fields easier to inspect by returning one JSON response. Replace MODEL_NAME with an already installed local model from ollama list; do not use a cloud model for this comparison. The request performs inference and consumes resources, but does not delete model data.
curl -sS http://localhost:11434/api/generate \
-H 'Content-Type: application/json' \
-d '{"model":"MODEL_NAME","prompt":"Explain what a file cache does in two sentences.","stream":false,"options":{"num_predict":128}}'
Run the same request again while the model remains loaded. With streaming disabled, the terminal displays the response after completion, so this command is for the returned timing fields, not for timing the first token by eye. If the request fails, keep its error and stop the comparison rather than interpreting a missing field as zero.
| Returned field | How to use it |
|---|---|
load_duration |
Compare first and repeated loading time |
prompt_eval_count and prompt_eval_duration |
See how much input was processed and its cost |
eval_count and eval_duration |
Compare output generation for the same workload |
total_duration |
Keep the whole-request cost beside the component timings |
The documented durations are nanoseconds. Divide a duration by 1,000,000,000 to obtain seconds. For output speed, divide eval_count by eval_duration / 1,000,000,000, provided the duration is positive. As an arithmetic example, 100 tokens over 5,000,000,000 nanoseconds is 20 tokens per second; that is not a measured result for any Mac or model.
Do not divide output tokens by total duration and then call it pure generation speed. That would include loading and input work. Also note whether the repeated prompt uses cached input, because a faster second request may reflect both a warm model and prompt reuse. Keep the full response rather than reporting just the most flattering number.
See what is actually loaded
In Terminal, inspect the current state:
ollama ps
The Ollama FAQ explains the PROCESSOR column. It can show GPU, CPU or a split. The hardware guide documents Metal acceleration on Apple GPUs. If you expected a local model to use the GPU, the running result is more useful than an assumption based on the Mac's name.
Also confirm that the request is going to the local server you are inspecting. A front end may point to another host or a cloud model. In that case, the local ollama ps output does not describe the remote request.
Reduce the context before blaming the model size
Model files are only part of the memory requirement. A larger context needs additional memory, and concurrent requests add work. Ollama's context-length documentation describes hardware-dependent defaults and the app's context control. Do not assume every installation has the same default.
For a controlled test, use a short prompt, one request and a smaller context that still contains the information needed for that test. If the full coding task later requires more context, restore enough to preserve its meaning. A faster answer that silently loses required instructions is not a successful optimization.
Try a smaller model or quantization only as a separate comparison. It changes both resource use and answer quality. Keep a few representative questions so you can assess whether the faster option remains useful.
Test a context change without making it permanent
For a short diagnostic prompt, the API accepts a per-request context option. In the preceding request, add "num_ctx":4096 inside options alongside num_predict, using a local model that supports that context. This is an example test size, not a recommended setting for every model or coding task.
Keep the model and prompt unchanged, then inspect the running model with ollama ps and compare memory pressure. Do not shrink the context around a large conversation and assume the answer still includes every instruction. First compare a small task that fits; afterward test the actual workload with enough context for its inputs.
The FAQ and dedicated context-length page describe defaults differently, so this guide does not rely on a universal default. An app setting, a front end or a request-level option may also affect the running value. Where the installed version reports CONTEXT in ollama ps, record that value alongside PROCESSOR rather than inferring it from the model file size.
A lower memory reading is not the only success condition. The task must still complete with acceptable answers, and the rest of the Mac must remain usable. If a smaller context drops important facts or the change makes no repeatable difference, remove the test option and restore the previous working setup.
Watch the whole Mac during generation
Open Activity Monitor › Memory and watch pressure while generating, not just after the response finishes. Apple Silicon uses shared system memory, so other apps also matter. A model fitting on disk does not establish that it fits comfortably alongside the rest of your workload.
Save work and close an unnecessary heavy task, then repeat the same request. If pressure improves and the slowdown changes with it, you have a useful lead. The memory-pressure guide covers how to read the Mac's indicators without treating every cached byte as waste.
Unload an idle model without deleting it
First wait for any request using the model to finish. To release a loaded model you no longer need, use ollama stop followed by its exact name from ollama ps:
ollama stop MODEL_NAME
Replace MODEL_NAME before running the command. This unloads the model from memory. It does not delete its downloaded files, and the next request may pay the loading cost again. Repeatedly unloading a model between requests can therefore make the experience slower.
If disk space is the actual constraint, review stored models separately in the AI model cleanup guide. Keep locally created models and anything you cannot reliably download again. For performance, compare one change at a time and keep the result tied to the same workload.
Investigate a mismatch with the server log
If the local request remains slow or the processor split is unexpected, Ollama's troubleshooting guide locates the Mac server log at ~/.ollama/logs/server.log. Read the portion around the test time and look for loading failures, memory allocation problems or the selected execution backend. For a manually started server, the corresponding messages may be in its terminal instead.
Record the Ollama version, exact model tag, context, processor split and the stage that dominates the timings. Review log excerpts for private prompts and local paths before sharing them. Do not change several GPU or server environment variables merely because they appear in an old optimization post; the log should first identify the mismatch that a change is meant to address.