Ornith 1.5 9B and 35B-A3B Benchmark on RTX 5090

We benchmarked Ornith 1.5 9B and 35B-A3B against Gemma 4-31B, Muse Glimmer 30B and Qwen 3.8 27B on one RTX 5090, and found that every advertised context length is a fiction.

Aug 25, 202620 min readFollow

Topics You Will Master

Reading a GGUF header to find out what a model card refuses to tell you
Why a mixture-of-experts model with 35B parameters can outrun a dense 9B
Measuring KV cache cost per token, and why it decides your real context limit
Why "max context that loads" is a meaningless number on Windows, and what to measure instead

ornith-ai published two models on Hugging Face: Ornith-1.5-9B-GGUF and Ornith-1.5-35B-A3B-GGUF. The 35B card claims it beats Gemma 4-31B and Muse Glimmer 30B by wide margins on agentic coding.

In this blog, we will run both Ornith models against those two rivals plus Qwen 3.8 27B on a single RTX 5090, across nine measurements. We will also find out why the context length printed on every one of those model cards is not the context length you actually get.

Bestseller

Master Langchain v1 and Ollama - Chatbot, RAG and AI Agents

Master Langchain v1, Local LLM Projects, Ollama, DeepSeek, LLAMA 3.2, Complete Integration Guide.

Enroll on Udemy 30 day refund, lifetime access

Setup: One Card, One Runtime, Five Models

Everything below ran on one machine in one session, so no number here is being compared against something measured on a different day.

  • GPU: RTX 5090, 32 GB VRAM, full GPU offload
  • Runtime: llama-server build 10448 on Windows 11
  • Quantization: Q4_K_M for all five models, so quant class is never a confound
  • KV cache: f16 with flash attention on, except where we sweep that on purpose
  • Grading: pure Python functions, no judge model anywhere

Every model was started the same way.

BASH
llama-server.exe -m Ornith-1.5-35B-Q4_K_M.gguf --host 127.0.0.1 --port 8099 -c 8192 -ngl 999 -fa on -np 1 --jinja --no-warmup --metrics

Important

The --jinja flag matters more than it looks. Without it, the <think> block lands inline in content instead of reasoning_content, so any script counting reasoning tokens quietly reports zero for a model that is thinking normally.

For decode speed we used the raw /completion endpoint with ignore_eos, so every model produced exactly 512 tokens. That removes the most common way a benchmark lies to itself, which is a model stopping early and looking fast.

Advertisement

GGUF Teardown: Ornith Is Qwen 3.5 Underneath

Neither Ornith card publishes a layer count. Both talk about an end-to-end self-improvement loop instead. So we opened the files and read the headers.

PYTHON
from gguf import GGUFReader

r = GGUFReader("Ornith-1.5-35B-Q4_K_M.gguf")
for field in r.fields.values():
    if "architecture" in field.name or "expert" in field.name:
        print(field.name, "=", field.contents())
PYTHON
general.architecture = qwen35moe
qwen35moe.expert_count = 256
qwen35moe.expert_used_count = 8
qwen35moe.expert_feed_forward_length = 512
qwen35moe.expert_shared_feed_forward_length = 512

The 9B reports qwen35 and the 35B reports qwen35moe. Both are Qwen 3.5 with different weights. Let me tabulate the whole field for your better understanding.

Model Architecture Blocks Residual Heads KV heads Head dim Experts MTP head
Ornith 1.5 9B qwen35 32 + 1 4096 16 4 256 dense yes
Ornith 1.5 35B-A3B qwen35moe 40 + 1 2048 16 2 256 256 / 8 active yes
Qwen 3.8 27B qwen35 64 + 1 5120 24 4 256 dense yes
Gemma 4-31B gemma4 60 5376 32 16 / 2 512 dense no
Muse Glimmer 30B muse-glimmer 52 6656 32 2 128 dense no

Here, we can see that there is no new architecture in Ornith 1.5. Whatever these models are worth comes from post-training, not from a structural idea.

The 35B is an unusually fine-grained mixture. It hangs 256 experts of width 512 off a residual stream only 2,048 wide, and activates 8 of them plus a shared expert per token. That works out to roughly 3B parameters touched per forward pass.

Note

Gemma 4-31B is dense. The gemma4:26b sitting in most Ollama stores is a different model with 128 experts. Same family name, different architecture, so make sure you are comparing the one the card actually names.

Decode Speed: The Mixture Wins by a Wide Margin

Now the first real measurement. Five models, 512 tokens each, five content types, speculative decoding off.

Horizontal bar chart of decode speed showing Ornith 35B-A3B at 272 tokens a second, Ornith 9B at 192, and Muse Glimmer, Qwen 3.8 and Gemma 4 clustered between 69 and 79

Ornith 35B-A3B runs at 272 tokens a second. That is 3.5 times Qwen 3.8 27B and 42% faster than the Ornith 9B, while being four times the file size on disk.

In simple words, decode speed on a single card is set by how many parameters the model reads per token, not by how many it stores.

Scatter plot of decode speed against active parameters per token, with Ornith 35B-A3B alone in the top left at 3B active and 272 tokens a second

One more thing worth noting from these runs. The spread across counting, code, JSON, essay and fiction was between 0.3% and 1.4% for every model. With speculative decoding off, decode speed does not care what you are generating.

Advertisement

Prompt Reading Speed, and the Cost of Being a Mixture

Decode speed is only half of what you feel. The other half is how fast the model reads your prompt.

Line chart of prefill speed against prompt length from 512 tokens to 128k, with Ornith 35B-A3B starting lowest at 512 tokens then climbing above every model except Ornith 9B

Here, we can see the one real weakness of the mixture model. At a 512 token prompt it reads at 1,223 tokens a second, against 7,493 at 8k. Routing 256 experts carries a fixed cost on every forward pass, and on a short prompt there are not enough tokens to spread that cost over.

So for short interactive turns the 9B is roughly five times faster to first token, and the throughput charts hide that completely.

KV Cache Is the Real Divider

The KV cache is the memory the model keeps for every token already in context. It is the number that decides how much context your card can hold, and it varies far more between these models than their file sizes do.

Horizontal bar chart of KV cache cost per token, from Muse Glimmer at 13 KiB to Gemma 4-31B at 80 KiB, with the full 262k window cost beside each bar

Every qwen35 model in this test caches KV on only a quarter of its layers. The Ornith 9B keeps 8 of 32, the 35B keeps 10 of 40, and Qwen 3.8 keeps 16 of 64. None of the three model cards mentions this.

Gemma and Muse both use sliding window attention, and llama-server allocates two caches for each of them.

PLAINTEXT
llama_kv_cache: size = 5120.00 MiB ( 65536 cells, 10 layers, 1/1 seqs), K (f16): 2560.00 MiB, V (f16): 2560.00 MiB
llama_kv_cache: size = 1200.00 MiB (  1536 cells, 50 layers, 1/1 seqs), K (f16):  600.00 MiB, V (f16):  600.00 MiB

That is Gemma at 64k context. Its 50 windowed layers are capped at 1,536 cells and cost a flat 1,200 MiB no matter how long the context gets. But its 10 full attention layers have a head dimension of 512, and those alone cost 5,120 MiB. The windowing saves it from being far worse, and it still ends up the most expensive model per token in the group.

Quantizing the KV cache behaves identically for all five models, so it is a uniform lever rather than a per-model tuning knob.

KV cache type Size at 64k Saving
f16 baseline none
q8_0 53% of f16 47%
q4_0 28% of f16 72%
Advertisement

Context Ceilings Are Cliffs, Not Slopes

This is the part that surprised us, and it is the reason this article exists.

All five models advertise 262,144 tokens. All five of them start at 262,144 and report it back cleanly.

BASH
curl -s http://127.0.0.1:8099/props | python -c "import json,sys; print(json.load(sys.stdin)['default_generation_settings']['n_ctx'])"
OUTPUT
262144

That number is worthless, and here is why.

Caution

On Windows, a CUDA allocation that exceeds VRAM does not fail. The driver backs it with system RAM over PCIe. The server starts, reports the full context, logs no warning, and then runs at a fraction of its speed.

We caught it in Gemma's own memory numbers. As we raised the context from 155,648 to 262,144, its KV cache grew by 8.3 GiB while measured VRAM never moved off 31.5 GiB.

Context KV cache VRAM used
155,648 13,360 MiB 31,458 MiB
209,920 17,600 MiB 31,457 MiB
262,144 21,680 MiB 31,503 MiB

Here, we can see that the last 8 GiB of cache went somewhere other than the GPU, and nothing told us.

So "does it load" has no failure point on this platform, and asking that question gives an answer that is always yes. Instead we measured the point where decode speed falls off, using the model's own short-context rate as the reference.

PYTHON
def usable_ceiling(model, floor_fraction=0.90):
    """Largest context where decode stays within 90% of the small-context rate."""
    reference = decode_at(model, ctx=8192)
    floor = reference * floor_fraction
    ctx, best = 65536, 8192
    while ctx <= 262144:
        if decode_at(model, ctx) >= floor:
            best, ctx = ctx, ctx * 2
        else:
            break
    return best

Line chart of decode speed against allocated context for all five models, with Ornith 9B, Ornith 35B-A3B and Muse Glimmer flat to 262k while Qwen 3.8 falls off at 262k and Gemma 4-31B falls off at 152k

The drop is a cliff, not a gentle decline.

Model Usable context Of advertised Normal rate Past the cliff
Ornith 1.5 9B 262,144 100% 191.5 tok/s no cliff
Ornith 1.5 35B-A3B 262,144 100% 269.1 tok/s no cliff
Muse Glimmer 30B 262,144 100% 79.5 tok/s no cliff
Qwen 3.8 27B 245,760 94% 77.3 tok/s 2.9 tok/s
Gemma 4-31B 147,456 56% 69.7 tok/s 28.3 tok/s

Qwen 3.8 holds 76.9 tokens a second at 245,760 and collapses to 2.9 at 262,144. A 7% increase in context costs 96% of the throughput. Gemma loses 59% of its speed for 5% more context, and 44% of its advertised window is simply not available.

Ornith 35B-A3B is the only large model here that delivers its full advertised window at full speed, and it does it with almost 6 GiB to spare, because 20 KiB per token across 262k tokens is only 5 GiB of cache.

Advertisement

Long Context in Practice

Next we placed a fact inside documents of 16k, 64k and 128k tokens, at 10% and 90% depth, and asked for it back. All five models found every needle at every depth, 6 out of 6 each. Retrieval accuracy is not what separates them.

Horizontal bar chart of seconds to answer a question about a 128k token document, from Ornith 9B at 23.6 seconds to Gemma 4-31B at 205.5 seconds

Gemma takes three and a half minutes to answer what Ornith answers in 26 seconds. Part of that is the spill we just described, because at the 139,264 context this phase used, Gemma was already past its cliff.

Muse Glimmer deserves a mention here. Its prefill speed decays only 20% from 16k to 128k, against 46% for Qwen 3.8, which is exactly what sliding window attention is supposed to buy.

The MTP Head Nobody Documented

While reading the headers we found something neither Ornith card mentions. Both GGUF files carry a nextn block, which is a multi-token prediction head used for speculative decoding.

PLAINTEXT
blk.40.nextn.eh_proj.weight [4096, 2048] Q4_K
blk.40.nextn.enorm.weight [2048] F32
blk.40.nextn.hnorm.weight [2048] F32
blk.40.nextn.shared_head_norm.weight [2048] F32

llama-server ignores those tensors and prints them as unused unless we ask for them.

BASH
llama-server.exe -m Ornith-1.5-35B-Q4_K_M.gguf -c 8192 -ngl 999 -fa on --jinja --spec-type draft-mtp --spec-draft-n-max 4

So, here comes the catch. It helps on some content and actively hurts on the rest.

Grouped bar chart of MTP speedup by content type for Qwen 3.8, Ornith 9B and Ornith 35B-A3B, with all three above 1.0 on counting, code and JSON, and both Ornith models below 1.0 on essay and fiction

Acceptance rate explains all of it. On structured output the draft head guesses the next tokens correctly 63% to 86% of the time. On prose that falls to about 30%, and below roughly 40% the cost of drafting exceeds what it saves.

Qwen 3.8's head is clearly better trained than either Ornith head, reaching 2.36 times on JSON where the Ornith 35B manages 1.16.

Warning

This is not a free speedup. Two greedy runs with MTP off are bit identical, but with MTP on the output diverges, on 14 of the 15 model and content combinations we tested. Turning off --spec-draft-backend-sampling changed nothing. Treat MTP as a different configuration that needs its own quality check, not as a transparent accelerator.

Concurrency: Where the Mixture Pulls Away

Single stream speed is not the whole story if you are serving more than one request.

Line chart of aggregate throughput at 1, 4 and 8 parallel requests, with Ornith 35B-A3B reaching 669 tokens a second and Gemma 4-31B falling from 192 to 163

Ornith 35B-A3B reaches 669 tokens a second across 8 slots, more than double the best non-Ornith model.

Notice that the two Ornith models have the worst relative scaling, at about 2.7 times, while Muse Glimmer scales best at 3.7 times. That is only because the Ornith models start from such a high single stream baseline, and Muse still ends up at less than half the absolute throughput.

Gemma goes backwards between 4 slots and 8. That is the third separate symptom of the same problem: on a 32 GB card this model is memory bound, so every axis that adds memory pressure breaks it.

Advertisement

Accuracy and Thinking Economics

We ran 12 reasoning problems with objectively checkable answers, graded by a function that extracts the final ANSWER: line. No judge model.

Out of 40 runs across five models, 39 were correct. The only miss was Qwen 3.8 on one hard problem. Nothing hit its token cap.

Horizontal bar chart of median seconds to a correct hard answer, from Ornith 35B-A3B at 7.8 seconds to Gemma 4-31B at 59.7 seconds, with median token counts beside each bar

Since accuracy is saturated, the useful question becomes what a correct answer costs.

Model Hard tier Median tokens Thinking share Median seconds
Ornith 1.5 35B-A3B 8/8 2,110 70% 7.8
Ornith 1.5 9B 8/8 3,481 83% 18.1
Qwen 3.8 27B 7/8 1,420 89% 18.9
Muse Glimmer 30B 8/8 1,518 95% 19.3
Gemma 4-31B 8/8 3,948 79% 59.7

Two things are worth pulling out of that table.

Token count and wall clock point in opposite directions. Qwen 3.8 is the most economical model in the group at 1,420 median tokens, and it still takes 2.4 times longer than Ornith 35B to produce an answer, purely because it decodes at 77 tokens a second instead of 272. Quoting either number on its own would give the wrong impression.

The Ornith models also think proportionally less. The 35B spends 70% of its output inside the think block, against 95% for Muse Glimmer and 89% for Qwen 3.8. It commits to an answer sooner.

The 9B is the interesting counter case. It reaches the same 8 out of 8 by thinking harder, 3,481 tokens against its larger sibling's 2,110, and pays 18.1 seconds instead of 7.8 for the identical score.

Agentic Tool Use: Everything Tied

Last, we built a tool-calling test with a virtual database and a small source tree, 10 tasks run at two seeds each. The tools return fixed data, and nothing executes model-written code.

The hard tier included an ambiguous name lookup that punishes guessing, a manager chain that needs five chained calls, and a proposed bug fix that looks right and is not.

Model Solved Malformed calls Mean seconds per task Mean thinking characters
Ornith 1.5 35B-A3B 18/18 0 4.9 2,256
Ornith 1.5 9B 18/18 0 6.2 2,408
Qwen 3.8 27B 18/18 0 10.6 1,333
Gemma 4-31B 18/18 0 16.6 2,440
Muse Glimmer 30B 18/18 0 23.4 6,192

Everything solved everything, with zero malformed tool calls in 100 runs.

Note

That means our test cannot check the Ornith card's headline claim about agentic coding. At this difficulty there is no margin between any of these models, because they are all at ceiling. This is a limit of our test, not evidence against the claim. The benchmarks behind that claim, SWE-bench Pro and Terminal-Bench, are multi-hour agent runs against real repositories.

Cost separates them again. Same 18 out of 18, and Ornith 35B finishes a task in 4.9 seconds while Muse Glimmer takes 23.4 and spends 6,192 characters thinking to Ornith's 2,256.

We also had to throw out one of our own tasks. It ended with "report the timezone of that region", which reads as asking for the timezone alone. All five models answered UTC+1, and our grader wanted the datacenter too, so it marked all five wrong. That was an ambiguous prompt on our side, not a model failure, so we excluded it and fixed the wording.

Advertisement

Which Model Should We Run

Model Decode Weights tok/s per GiB Best at
Ornith 1.5 9B 192.1 5.2 GiB 36.7 Small footprint, short prompts, full context in 14.6 GiB
Ornith 1.5 35B-A3B 272.1 19.7 GiB 13.8 Everything else on a 32 GB card
Muse Glimmer 30B 79.3 15.6 GiB 5.1 Cheapest KV cache, flattest long-context decay
Qwen 3.8 27B 76.7 15.4 GiB 5.0 Best MTP head, fewest thinking tokens
Gemma 4-31B 68.9 17.8 GiB 3.9 Not this card

Ornith 1.5 35B-A3B is the model to run on a 32 GB card. Fastest decode, fastest correct answer, highest throughput under load, and the only large model that holds a real 262k context. The two prices are 19.7 GiB of VRAM and slow prefill on very short prompts.

Ornith 1.5 9B is the efficiency winner at 36.7 tokens a second per gibibyte, roughly seven times Gemma's rate, and it holds the full context window in 14.6 GiB.

Gemma 4-31B is a poor fit for this hardware. Not because of its answers, which matched everyone, but because 80 KiB of KV per token breaks it on every axis that adds memory pressure.

What We Did Not Test

Being clear about the gaps matters more than a tidy conclusion.

  • Vision. Both Ornith repositories ship an mmproj file and their templates carry image tokens. We tested text only.
  • Quality cost of KV quantization. We measured the sizes at q8_0 and q4_0, not what they do to output.
  • Quality cost of MTP. We proved the output changes, not whether it gets worse.
  • Agentic coding at SWE-bench scale, which is where the card's main claim lives.

This is how a local benchmark works: measure what the hardware actually does, name the number the model card leaves out, and say plainly which questions you could not answer.

Found this useful? Keep building with me.

New tutorials every week on YouTube: or go deeper with a full structured course.

Find this tutorial useful?

Subscribe to our YouTube channels for more practical production walk-throughs.

Discussion & Comments