Rapid-MLX vs oMLX vs LM Studio: 1.50× 27B decode on M5 Max

Rapid-MLX delivered 173.4 tok/s on one stream with Qwen3.6-35B and 37.9 tok/s with Qwen3.8-27B on the M5 Max runs, ahead of oMLX and LM Studio.

Disclosure: we build Rapid-MLX. All measurements below come from the published runs.

For the direct MLX vs Ollama speed question, read the measured Rapid-MLX vs Ollama benchmark. For a feature-based choice among Rapid-MLX, Ollama and LM Studio, use the three-tool guide.

Qwen3.8-27B 4-bit on a Mac Studio, M5 Max, 36 GB

Rapid-MLX measured 37.9 tok/s on one stream and 82.8 tok/s across four. On the same weights, oMLX measured 25.3 tok/s and 75.3 tok/s; LM Studio measured 26.0 tok/s and 69.7 tok/s.

rapid-mlx serve qwen3.8-27b-4bit
Scenario Rapid-MLX 0.16.1 default oMLX 0.7.0 LM Studio (MLX)
Decode, 1 stream 37.9 tok/s 25.3 tok/s 26.0 tok/s
4 streams, aggregate 82.8 tok/s 75.3 tok/s 69.7 tok/s

Measurement notes. Mac Studio, M5 Max, 36 GB; 2026-10-12. Single run per engine; small differences (under ~5%) are within run-to-run variation. Rapid-MLX 0.16.1 default used MTP speculative decoding on a text-only lane with image input off. With --no-spec-decode it serves images. oMLX ran with its documented SSD cache directory enabled; LM Studio ran headless with its MLX runtime. All three used the same model weights. Scenario JSON, harness, versions, and summary are published.

Qwen3.6-35B 4-bit on a Mac Studio, M5 Max, 36 GB

Rapid-MLX measured 173.4 tok/s on one stream and 293.9 tok/s across four. On the same weights, oMLX measured 145.8 tok/s and 281.9 tok/s; LM Studio measured 124.5 tok/s and 265.6 tok/s.

rapid-mlx serve qwen3.6-35b-4bit
Scenario Rapid-MLX 0.16.1 default oMLX 0.7.0 LM Studio (MLX)
Decode, 1 stream 173.4 tok/s 145.8 tok/s 124.5 tok/s
4 streams, aggregate 293.9 tok/s 281.9 tok/s 265.6 tok/s
Tool calls passed (30 prompts) 30/30 29/30 29/30
After restart: turn 1 0.27 s 0.34 s 18.27 s
TTFT, ~2k-token prompt 0.55 s 1.14 s 1.49 s

Measurement notes. Mac Studio, M5 Max, 36 GB; 2026-10-12. Single run per engine; small differences (under ~5%) are within run-to-run variation. Rapid-MLX 0.16.1 default used MTP speculative decoding on a text-only lane with image input off. With --no-spec-decode it serves images. oMLX ran with its documented SSD cache directory enabled; LM Studio ran headless with its MLX runtime. All three used the same model weights. Scenario JSON, harness, versions, and summary are published.

Qwen3.5-9B at a glance

pip install rapid-mlx
rapid-mlx serve qwen3.5-9b-4bit

Measured on a Mac Studio, M5 Max, 36 GB (October 2026)

Rapid-MLX 0.16.1 default, oMLX 0.7.0 and LM Studio llmster 0.0.25 with MLX runtime 1.11.0, all on Qwen3.5-9B 4-bit. Lower TTFT is faster; higher token throughput is faster.

Scenario Rapid-MLX 0.16.1 default oMLX 0.7.0 LM Studio (MLX)
Decode, 1 stream 115.5 tok/s 78.0 tok/s 81.1 tok/s
4 streams, aggregate 248.2 tok/s 224.6 tok/s 230.0 tok/s
Tool calls passed (30 prompts) 30/30 30/30 30/30
Agent session: turns 2–10, median 0.233 s 0.238 s 0.613 s
After restart: turn 1 0.197 s 0.265 s 32.678 s
After restart: turns 2–10, median 0.229 s 0.230 s 0.611 s
After restart: 10 turns, total 2.275 s 2.340 s 37.842 s
Agent session: 10 turns, total 11.547 s 10.772 s 37.894 s
Agent session: turn 1, cold 9.442 s 8.576 s 32.694 s
TTFT, ~2k-token prompt 0.815 s 0.747 s 2.780 s
TTFT, ~16k-token prompt 6.089 s 5.721 s 21.743 s

October measurement notes. Mac Studio, M5 Max, 36 GB; Qwen3.5-9B 4-bit; 2026-10-12. Single run per engine; small differences (under ~5%) are within run-to-run variation. Rapid-MLX 0.16.1 default used MTP speculative decoding on a text-only lane with image input off. With --no-spec-decode it serves images, but measured 80.1 tok/s on one stream and 77.0 tok/s across four streams. oMLX ran with its documented SSD cache directory enabled; LM Studio ran headless with its MLX runtime. oMLX and LM Studio were measured earlier the same day on the same machine as Rapid-MLX. Scenario JSON, harness, versions, and summary are published.

The September runs use the script, driver, raw per-request JSON and derived summary.

oMLX vs LM Studio

On this run LM Studio decoded faster than oMLX on one stream and across four streams; oMLX had shorter cold prompt TTFT and first agent turn. Both passed all 30 tool-call prompts. Rapid-MLX led both decode rows against both: 115.5 tok/s on one stream and 248.2 tok/s across four. Its 0.20 s first turn after restart was close to oMLX's 0.27 s and much shorter than LM Studio's 32.7 s. See the oMLX and LM Studio pages for focused comparisons.

Scenario Rapid-MLX 0.16.1 default oMLX 0.7.0 LM Studio (MLX)
Decode, 1 stream 115.5 tok/s 78.0 tok/s 81.1 tok/s
4 streams, aggregate 248.2 tok/s 224.6 tok/s 230.0 tok/s
After restart: turn 1 0.197 s 0.265 s 32.678 s
Agent session: turn 1, cold 9.442 s 8.576 s 32.694 s
TTFT, ~2k-token prompt 0.815 s 0.747 s 2.780 s
TTFT, ~16k-token prompt 6.089 s 5.721 s 21.743 s

September 2026 results on other Macs

The following M4 Pro Mac mini (48 GB) and M3 Pro Mac (18 GB) results are separate September runs. Ollama was not measured on the M5 Max.

The September short version

On an M4 Pro Mac mini with 48 GB (Qwen3.5-9B at 4-bit), with each engine at its defaults except the settings listed under the table. The Rapid-MLX rows are Rapid-MLX 0.15.3 (measured at commit 1394f16, which 0.15.3 includes); the previous release, 0.15.2, is compared in What changed in Rapid-MLX.

Rapid-MLX vs mlx-lm

A separate, task-by-task benchmark against mlx-lm, Apple's MLX library and server (2026-10-04, Rapid-MLX 0.15.6 against mlx-lm 0.32.0, Mac mini M4 Pro, 48 GB, greedy decoding, same weights): up to 4× faster decode on whole-file code edits (Qwen3.5-9B 4-bit), 1.50× at the median of the 18 everyday tasks that stream text, close to a tie on long-prompt agent turns. Per-task results, method and raw data: Rapid-MLX vs mlx-lm benchmark.

Feature comparison

What each project ships today, from its own docs and our installs. "Yes" means documented and working in the version we ran, not a roadmap.

Rapid-MLX oMLX Ollama LM Studio mlx-lm (mlx_lm.server)
What it is OpenAI- and Anthropic-compatible inference server for Apple Silicon, built on MLX Inference server for Apple Silicon, built on MLX, run from a macOS menu-bar app Cross-platform model runner and server Desktop app for downloading and chatting with models, with a local server Apple's reference MLX library; its server is a minimal example
OpenAI API Yes Yes Yes (plus its own /api) Yes (plus its own REST API) Yes, basic
Anthropic /v1/messages Yes Yes Yes (since v0.14) Yes (since 0.4.1) No
GUI Rapid-MLX Desktop (macOS app); CLI Menu-bar app plus a web admin panel Desktop app with chat; CLI Full desktop app; lms CLI None (Python CLI)
License Apache-2.0 (engine and Desktop) Apache-2.0 MIT Free to use, closed-source app MIT
Platforms macOS on Apple Silicon macOS on Apple Silicon macOS, Windows, Linux macOS, Windows, Linux macOS on Apple Silicon (MLX also has Linux backends)
Model format / backend MLX MLX (mlx-lm) GGUF (llama.cpp); MLX engine in preview on Macs with 32 GB+ GGUF (llama.cpp) and MLX MLX
Concurrent requests Continuous batching Continuous batching Parallel slots (OLLAMA_NUM_PARALLEL), not for every architecture Parallel predictions (--parallel) Batching (off with a quantized KV cache)
KV / prompt cache In-memory prefix cache; written to disk at shutdown if it fits a short time budget, reloaded at start In-memory hot tier plus an SSD cold tier that survives restarts In-memory, per loaded model In-memory In-memory prompt cache
Tool-call parsing Dedicated parser per model family, picked by the model alias Auto-detected per model family (JSON <tool_call>, Mistral, GLM, MiniMax, Kimi and others) Per-model templates Per-model templates From the tokenizer's chat template
Model catalog Curated aliases with per-model profiles, or any MLX repo on Hugging Face Any mlx-lm model; downloader in the admin panel ollama.com library Hugging Face search in the app Any MLX repo on Hugging Face
Install brew install rapid-mlx, pip, one-line script, or the Desktop DMG DMG, Homebrew tap, or pip from a release wheel DMG, Homebrew, or script DMG pip install mlx-lm

Sources: each project's README and docs, checked 2026-09-26 (oMLX, Ollama Anthropic compatibility, Ollama MLX preview, LM Studio Anthropic endpoint, mlx-lm server). Rapid-MLX flags are from rapid-mlx serve --help at 0.15.2.

Measured on an M4 Pro Mac mini (48 GB), September 2026

Engine (config) Decode, 1 stream TTFT, ~2k-token prompt TTFT, ~16k-token prompt 4 streams, aggregate Tool calls (30 prompts)
Rapid-MLX 0.15.3 (@1394f16) (PFlash off) 66.1 tok/s 5.30 s 42.8 s 68.3 tok/s 30/30
Rapid-MLX 0.15.3 (@1394f16) (defaults, PFlash on) not run 5.31 s 8.23 s not run not run
oMLX 0.7.0rc1 (SSD cache on) 51.2 tok/s 5.40 s 41.7 s 97.1 tok/s 30/30
Ollama 0.34.3 (qwen3.5:9b, Q4_K_M) 38.4 tok/s 6.35 s 49.4 s 37.4 tok/s 30/30
mlx-lm 0.31.3 (mlx_lm.server) 47.7 tok/s 5.51 s 43.6 s 96.6 tok/s 30/30

Conditions. Mac mini, Apple M4 Pro, 48 GB unified memory, macOS 26.5.1, on AC power, idle before each engine (GPU 0% after a 60 s rest + 10 idle seconds). Model: Qwen3.5-9B at 4-bit (MLX engines: mlx-community/Qwen3.5-9B-4bit @ 8b2b98c, MTP sidecar mlx-community/Qwen3.5-9B-MTP-4bit @ 222dfd2; Ollama: qwen3.5:9b, GGUF Q4_K_M, id 6488c96fa5fa), same as run 2. One engine at a time, loopback only, temperature 0, streaming. Before each engine the driver rested 60 s and waited for the GPU to read idle, and gave the engine a fresh home directory (no cache or settings carried over). The competitors were measured in run 3; Rapid-MLX 0.15.3 (measured at commit 1394f16, which 0.15.3 includes) was measured a few hours later the same night with the same harness and protocol in run 4 (the competitors' versions had not changed, so they were not re-run). Decode and TTFT cells are the median of 3 runs, the 4-stream cell the median of 2. Decode tok/s is (completion tokens − 1) / (last token − first token), using each engine's own token count. TTFT is request sent to the first streamed token of any kind, thinking included; each prompt starts with a random nonce so that no prefix cache applies. Engines group tokens into stream chunks differently (oMLX sends several tokens per chunk), which can add a fraction of a second to a TTFT. Every request asked for thinking explicitly (chat_template_kwargs.enable_thinking=true), because Rapid-MLX turns thinking off by default for casual requests while the others leave it on; the raw files store the generated text and reasoning, so you can check. Engine settings: Rapid-MLX with --pflash off (see below), everything else default, which for this model includes MTP speculative decoding; oMLX with its documented --paged-ssd-cache-dir; Ollama with a 32k context so no prompt was truncated and OLLAMA_NUM_PARALLEL=4 (Ollama 0.34.3 ignores it for this model and logs "model architecture does not currently support parallel requests"; its four streams' first tokens arrived about 7 s apart, one after another); mlx-lm's server at its defaults. Ollama loads its own GGUF Q4_K_M build of the model, the others load the same MLX 4-bit files.

Why the main Rapid-MLX row has PFlash off. PFlash is long-prompt prefill compression that keeps a fraction of the prompt's tokens (20% by default) before prefilling. It is off unless you pass --pflash auto or --pflash always; the build we measured turned it on by default for Qwen3.5 and Qwen3.6 models, so the main row passed --pflash off, which matches the default. With PFlash on, long prompts were much faster (8.23 s instead of 42.8 s at ~16k tokens; it did not engage on the agent session, whose requests carry tools), but the model then does not see every prompt token, so it is not a like-for-like comparison with engines that prefill all of them. We did not measure answer quality with PFlash on, and ran only the prefill and agent-session tests in that configuration.

On an 18 GB Mac, September 2026

MacBook Pro, Apple M3 Pro, 18 GB unified memory, macOS 15.6.1, on power. Competitors from run 2, Rapid-MLX 0.15.3 (measured at commit 1394f16, which 0.15.3 includes) from run 4, same protocol. On this machine oMLX refused one of its three ~16k-token requests with its prefill memory guard ("Prefill would require ~9.08 GB peak … dynamic ceiling is 9.00 GB"), so its ~16k cell is the median of the two that ran, and Ollama's four streams started about 11 s apart.

Engine (config) Decode, 1 stream TTFT, ~2k-token prompt TTFT, ~16k-token prompt 4 streams, aggregate Tool calls (30 prompts)
Rapid-MLX 0.15.3 (@1394f16) (PFlash off) 43.6 tok/s 5.50 s 44.7 s 62.3 tok/s 30/30
Rapid-MLX 0.15.3 (@1394f16) (defaults, PFlash on) not run 5.50 s 8.58 s not run not run
oMLX 0.7.0rc1 (SSD cache on) 27.9 tok/s 5.73 s 43.9 s 85.3 tok/s 30/30
Ollama 0.34.3 (qwen3.5:9b, Q4_K_M) 22.8 tok/s 6.24 s 49.9 s 22.5 tok/s 30/30
mlx-lm 0.31.3 (mlx_lm.server) 25.6 tok/s 5.87 s 45.6 s 80.7 tok/s 30/30

The coding-agent session

oMLX's pitch is that Claude Code "responds in 5 seconds, not 90" (omlx.ai): coding agents resend a long system prompt and tool list on every turn, and oMLX keeps that prefix's KV cache on SSD so it survives a restart. We replayed a Claude-Code-shaped session to measure exactly that: a 22,819-token first request (a long system prompt plus 30 tool schemas), then 10 user turns from a fixed transcript (the assistant replies are canned, so every engine sees identical prompts). Then we restarted the server, warmed it with an unrelated prompt, and replayed the same 10 turns. For Ollama, "restart" means unloading the model (ollama stop), which drops its KV cache the same way. Numbers are time to first token per turn; when a server sends nothing until its 16-token reply is complete, the number is time to the end of the stream instead, and the raw records flag those turns (ttft_fallback_end_of_stream).

M4 Pro, 48 GB:

Engine (config) Turn 1 (cold) Turns 2–10, median 10 turns, total After restart: turn 1 After restart: turns 2–10, median
Rapid-MLX 0.15.3 (@1394f16) (PFlash off) 65.1 s 0.49 s 69.6 s 12.3 s 0.49 s
Rapid-MLX 0.15.3 (@1394f16) (defaults, PFlash on) 65.3 s 0.49 s 69.8 s 12.3 s 0.49 s
oMLX 0.7.0rc1 (SSD cache on) 63.1 s 0.49 s 67.6 s 0.27 s 0.27 s
Ollama 0.34.3 (qwen3.5:9b, Q4_K_M) 73.4 s 0.41 s 76.9 s 73.1 s 0.41 s
mlx-lm 0.31.3 (mlx_lm.server) 65.7 s 0.47 s 69.7 s 65.7 s 0.47 s

M3 Pro, 18 GB:

Engine (config) Turn 1 (cold) Turns 2–10, median 10 turns, total After restart: turn 1 After restart: turns 2–10, median
Rapid-MLX 0.15.3 (@1394f16) (PFlash off) 68.5 s 0.69 s 74.9 s 13.0 s 0.67 s
Rapid-MLX 0.15.3 (@1394f16) (defaults, PFlash on) 68.1 s 0.69 s 74.5 s 13.0 s 0.65 s
oMLX 0.7.0rc1 (SSD cache on) 67.0 s 0.66 s 73.0 s 0.56 s 0.44 s
Ollama 0.34.3 (qwen3.5:9b, Q4_K_M) 77.6 s 0.44 s 81.4 s 76.9 s 0.44 s
mlx-lm 0.31.3 (mlx_lm.server) 71.4 s 0.85 s, 0.77 s; server failed on turn 4 n/a 68.9 s 0.86 s; server failed on turn 3

After one cold prefill, oMLX answered every turn in under a second; its first turn after a restart took 0.27 s on 48 GB and 0.56 s on 18 GB. Ollama and mlx-lm reused their caches within the session just as well, and lost them on restart. On 18 GB, mlx-lm's server died with a Metal out-of-memory error on turn 4, and after the restart on turn 3 (server log).

Rapid-MLX 0.15.3 (measured at commit 1394f16, which 0.15.3 includes) kept the session prefix resident on both machines: turns 2–10 prefilled only the 42–66 new tokens each, bringing it under a second like the others (0.49 s on 48 GB, 0.69 s on 18 GB), though still behind Ollama on both machines and slightly behind oMLX on 18 GB. At shutdown it saved the session to disk and reloaded it at start, so the first turn after the restart restored 18,944 of the 22,819 prompt tokens and prefilled the remaining 3,875: 12.3 s on 48 GB. That is far better than a full prefill but still well behind oMLX's 0.27 s. The save is not guaranteed: on 18 GB, one of the four shutdowns (the last one, after the restart replay, so no number above depends on it) skipped the entry because its predicted write time (3.1 s) did not fit the 3.5 s shutdown budget minus its 0.4 s commit headroom. Cache budgets and save results for every start are in each run's versions.json and server logs. The prompt token counts differ slightly between engines (about 150 tokens) because each renders the tool schemas through its own chat template.

What changed in Rapid-MLX

The first published version of this page measured the previous release, Rapid-MLX 0.15.2, and it lost the agent session badly on the 18 GB Mac: its prefix cache sized itself to 0.86 GB there, each ~0.96 GB session entry was "too large" to store, and every turn paid the full prefill; what it saved at shutdown did not include the session, so the first turn after a restart was a full prefill too. Commit 1394f16 (#3794) gives agent sessions a minimum cache budget on small-RAM Macs and makes the shutdown save fit in most cases (see above). Same harness, same protocol, PFlash off:

Rapid-MLX, agent session 0.15.2, 18 GB 0.15.3 (@1394f16), 18 GB 0.15.2, 48 GB 0.15.3 (@1394f16), 48 GB
Turns 2–10, median 70.0 s 0.69 s 0.50 s 0.49 s
Turn 1 after a restart 69.1 s 13.0 s 65.1 s 12.3 s

Install 0.16.2 with pip install rapid-mlx==0.16.2 or Rapid-MLX Desktop 0.16.2. The benchmark was measured at commit 1394f16, which 0.16.0 includes; it was not re-run on the release tag. The 0.15.2 numbers are in summary-run2.json and summary-run3-m4pro-48gb.json.

Tool calling

Thirty fixed prompts, each with the same eight tools (weather, calculator, web search, email, calendar, read file, shell, currency). A prompt passes when the first tool call names the right function and its JSON arguments contain the expected values. Non-streaming, temperature 0. The prompts, expected calls and every raw response are in the raw data.

Rapid-MLX 0.15.3 (@1394f16) (PFlash off): 30/30 · oMLX 0.7.0rc1 (SSD cache on): 30/30 · Ollama 0.34.3 (qwen3.5:9b, Q4_K_M): 30/30 · mlx-lm 0.31.3 (mlx_lm.server): 30/30. Every engine passed every prompt. These are single-call, clearly worded requests, so the result says the plumbing works on all four servers for this model; it does not rank them. Harder multi-step tool use is where parsers differ, and this test does not cover it.

Gaps in the September runs

What each tool is

Why Rapid-MLX

On the October M5 Max run, Rapid-MLX led both decode throughput rows against oMLX and LM Studio, passed 30/30 tool-call prompts, and answered the first turn after restart in 0.20 s. It is Apache-2.0 licensed and provides OpenAI and Anthropic APIs, per-model tool-call parsers, agent setup commands, a Desktop app and Homebrew installation (brew install rapid-mlx). Its measured default for this model used a text-only lane, as noted above.

Focused pages: Rapid-MLX vs mlx-lm · Rapid-MLX vs oMLX · Rapid-MLX vs LM Studio · Ollama alternative for Mac · our August Ollama/LM Studio/llama.cpp benchmark.

How these runs came about

We publish every run. Run 1 (18 GB) was superseded after a review found three flaws that favored Rapid-MLX or muddied the result: Rapid-MLX had thinking off by default while the other engines were thinking; the engines ran back to back in a fixed order with Rapid-MLX first, on the coolest machine; and one Rapid-MLX start overlapped the shutdown of the previous server. The same review caught two errors on the first version of this page: it said Ollama's four streams ran in parallel (they did not), and the server logs it cited were missing from the published data. Run 2 (18 GB) fixed all of that; run 3 repeated it on a 48 GB M4 Pro; run 4 re-measured only Rapid-MLX at commit 1394f16, which 0.15.3 includes, on both machines. The data README maps each table to its run.

Reproduce it

curl -O https://rapidmlx.com/blog/assets/compare-2026-09/bench_compare.py
# start any OpenAI-compatible server on loopback, then, per scenario a b c d e:
python3 bench_compare.py --engine NAME --base-url http://127.0.0.1:PORT/v1 --model MODEL --thinking on --scenario a --out a.json

The client is standard-library Python. run_all.sh is the driver we used: it starts and stops each server, rests between engines, and restarts the server for the agent session. It expects the engines installed in a scratch directory (W, see its header) and your normal Hugging Face cache in HF_HOME.

Frequently asked questions

Is Rapid-MLX faster than Ollama?

For decode, yes in our runs: on an M4 Pro Mac mini with 48 GB (Qwen3.5-9B at 4-bit), Rapid-MLX 0.15.3 (measured at commit 1394f16, which 0.15.3 includes) decoded 66.1 tok/s on one stream against Ollama's 38.4 tok/s, and 68.3 tok/s against 37.4 tok/s across four streams (Ollama serves this model one request at a time). In a long coding-agent session Ollama answered follow-up turns faster: a median of 0.41 s against 0.49 s for Rapid-MLX, and 0.44 s against 0.69 s on an 18 GB Mac. The previous release, 0.15.2, was far slower there (70.0 s); that is fixed in 0.15.3.

Rapid-MLX vs oMLX: which should I use?

On the October M5 Max run, Rapid-MLX 0.16.1 default led single-stream and four-stream decode and passed all 30 tool-call prompts. oMLX had shorter cold prompt TTFT and the first agent turn. The first turn after restart was close between them in this single run. Details and the September tables are on the Rapid-MLX vs oMLX page.

Does Rapid-MLX work with Claude Code?

Yes. Rapid-MLX serves the Anthropic Messages API at /v1/messages, so Claude Code connects with ANTHROPIC_BASE_URL (see Claude Code on a local model). oMLX, Ollama (v0.14+) and LM Studio (0.4.1+) also serve that API. In our replay of a 23k-token Claude Code session, Rapid-MLX 0.15.3 (measured at commit 1394f16, which 0.15.3 includes) answered follow-up turns in a median of 0.49 s on a 48 GB Mac and 0.69 s on an 18 GB Mac. The previous release, 0.15.2, re-prefilled the whole prompt every turn on the 18 GB Mac (70.0 s); that is fixed in 0.15.3.

Where is the raw data?

Every request's timings, the engine-reported token usage and every tool-call response are listed in raw/manifest.json, with the script (bench_compare.py), the driver (run_all.sh), the engine versions and flags (each run's versions.json) and the numbers used on this page (summary.json).