Hoe ik
de Arena meet.

11 tests · 2 tools · 1 GPU

De suite definieert voor elk model dezelfde 11 benchmarks op dezelfde DGX Spark: 6 closed-loop voor gecontroleerde throughput en 5 open-loop voor gedrag onder belasting. Per run wordt vastgelegd welke tests compleet, afgebroken of zonder data zijn. Hoort bij de gids LLMs draaien op de DGX Spark.

Eén snelheidsmeting laat niet zien hoe een model bij andere belasting reageert. Een model met hoge tokens/sec bij één stream kan onder twintig gelijktijdige requests sterk terugvallen. Een ander model houdt zijn throughput vast, maar laat nieuwe requests lang op hun eerste token wachten. Prima voor batch, vervelend voor chat.

Daarom meet ik de doorvoer bij vaste gelijktijdigheid (closed-loop) en bij onafhankelijk binnenkomende verzoeken (open-loop). Ik varieer ook de lengte van prompts en antwoorden. Dat laat zien hoe de snelheid en wachttijd veranderen per scenario.

11
benchmarks
3
repeats · closed-loop
42
seed · open-loop
Aclosed-loop

llama-benchy

Hoe schaalt de throughput bij een vast aantal gelijktijdige streams?

Closed-loop houdt per stream steeds een request actief: zodra er één klaar is, volgt de volgende. De suite test vaste concurrency-waarden van 1 tot 20. Elke cel draait drie keer en wordt gerapporteerd als mean ± stddev.

Ideaal voor: één gebruiker, batch-processing, code completion. Niet representatief voor: een chat-app met veel gelijktijdige sessies.

6 / 11 benchmarks→ 01 · 02 · 03 · 04 · 05 · 06
Bopen-loop

vllm bench serve

Hoe houdt het zich onder X gelijktijdige users die niet wachten op elkaar?

Open-loop plant arrivals onafhankelijk van wat de server al doet. Request rate en burstiness bepalen het patroon; bij 0,3 req/s zit er gemiddeld ongeveer 3,3 seconden tussen arrivals. De generator gebruikt seed 42, zodat dezelfde ingestelde belasting herhaalbaar is.

Resultaat: p50/p95 TTFT en per-user tokens/sec onder belasting. TTFT-getallen rapporteer ik wel (boven de 2s gaat je app traag voelen), maar ze sluiten geen modellen uit de ranking. Een open-looptest telt alleen mee als minimaal 99% van de requests slaagt.

5 / 11 benchmarks→ 07 · 08 · 09 · 10 · 11

Elke kaart komt rechtstreeks uit het versievaste benchmarkcontract. Klap "view command" uit voor het reproduceerbare commandotemplate en vervang ORG/MODEL en SERVED_MODEL_NAME. Op een modelpagina zijn die waarden al ingevuld vanuit de runmetadata.

01 · llama-benchyclosed-loop

Chat

Korte prompt met een lang antwoord. Toont de uitvoersnelheid en de wachttijd voor het eerste token.

pp (prompt)
1024
tg (gen)
1024
depth
0
concurrency
1 · 5 · 10
repeats
3

tokens/sec · ttft p50

3 repeats · mean ± stddevview command →hide command ↑
uvx llama-benchy==0.4.0 \
  --base-url http://localhost:8000/v1 \
  --model SERVED_MODEL_NAME \
  --pp 1024 \
  --tg 1024 \
  --depth 0 \
  --concurrency 1 5 10 \
  --runs 3 \
  --latency-mode generation \
  --format md
02 · llama-benchyclosed-loop

RAG · 8k context

Middelgrote context met een korter antwoord. Toont de kosten van promptverwerking bij 8k inputtokens.

pp (prompt)
8192
tg (gen)
512
depth
0
concurrency
5 · 10 · 20
repeats
3

tokens/sec · ttft p50

3 repeats · mean ± stddevview command →hide command ↑
uvx llama-benchy==0.4.0 \
  --base-url http://localhost:8000/v1 \
  --model SERVED_MODEL_NAME \
  --pp 8192 \
  --tg 512 \
  --depth 0 \
  --concurrency 5 10 20 \
  --runs 3 \
  --latency-mode generation \
  --format md
03 · llama-benchyclosed-loop

Lange output en agents

Korte instructie, veel output. Codegeneratie, rapporten of gestructureerde agent-output. Stresstest voor decode-doorvoer.

pp (prompt)
256
tg (gen)
4096
depth
0
concurrency
1 · 5 · 10
repeats
3

tokens/sec · ttft p50

3 repeats · mean ± stddevview command →hide command ↑
uvx llama-benchy==0.4.0 \
  --base-url http://localhost:8000/v1 \
  --model SERVED_MODEL_NAME \
  --pp 256 \
  --tg 4096 \
  --depth 0 \
  --concurrency 1 5 10 \
  --runs 3 \
  --latency-mode generation \
  --format md
04 · llama-benchyclosed-loop

Multi-turn kantoorwerk

Vijf beurten per gesprek, tien gesprekken parallel. Dicht bij hoe een team dit echt gebruikt, met groeiende context per beurt.

pp (prompt)
2048
tg (gen)
512
depth
4
concurrency
1 · 5 · 10
repeats
3

tokens/sec · ttft p50

3 repeats · mean ± stddevview command →hide command ↑
uvx llama-benchy==0.4.0 \
  --base-url http://localhost:8000/v1 \
  --model SERVED_MODEL_NAME \
  --pp 2048 \
  --tg 512 \
  --depth 4 \
  --concurrency 1 5 10 \
  --runs 3 \
  --latency-mode generation \
  --format md
05 · llama-benchyclosed-loop

Grote context · 25k

Stresstest met grote prompts. Laat zien hoeveel de wachttijd voor het eerste token oploopt bij 25k inputtokens.

pp (prompt)
4096 · 8192 · 16384 · 25000
tg (gen)
256
depth
0
concurrency
1 · 5 · 10
repeats
3

tokens/sec · ttft p50

3 repeats · mean ± stddevview command →hide command ↑
uvx llama-benchy==0.4.0 \
  --base-url http://localhost:8000/v1 \
  --model SERVED_MODEL_NAME \
  --pp 4096 8192 16384 25000 \
  --tg 256 \
  --depth 0 \
  --concurrency 1 5 10 \
  --runs 3 \
  --latency-mode generation \
  --format md
06 · llama-benchyclosed-loop

Gelijktijdigheid onder druk

25k context met twintig aanvragen tegelijk. Test 05 bevat al vijf en tien; hier wordt de gelijktijdige belasting verder verhoogd.

pp (prompt)
25000
tg (gen)
256
depth
0
concurrency
20
repeats
3

tokens/sec · ttft p50

3 repeats · mean ± stddevview command →hide command ↑
uvx llama-benchy==0.4.0 \
  --base-url http://localhost:8000/v1 \
  --model SERVED_MODEL_NAME \
  --pp 25000 \
  --tg 256 \
  --depth 0 \
  --concurrency 20 \
  --runs 3 \
  --latency-mode generation \
  --format md
07 · vllm bench serveopen-loop

Realistische kantoor-baseline

Random dataset, 4000 tokens in en 500 uit, aankomstsnelheid 0,3 met burstiness 0,7. Een rustig kantoor.

dataset
random
input / output
4000 / 500
rate (req/s)
0.3
prompts
200
burstiness
0.7

ttft p50/p95 · tokens/sec per gebruiker

200 prompts · seed 42view command →hide command ↑
docker exec vllm-bench vllm bench serve \
  --backend openai-chat \
  --base-url http://localhost:8000 \
  --endpoint /v1/chat/completions \
  --model ORG/MODEL \
  --tokenizer ORG/MODEL \
  --served-model-name SERVED_MODEL_NAME \
  --dataset-name random \
  --random-input-len 4000 \
  --random-output-len 500 \
  --random-range-ratio 0.9 \
  --num-prompts 200 \
  --request-rate 0.3 \
  --burstiness 0.7 \
  --percentile-metrics ttft,tpot,itl,e2el \
  --metric-percentiles 50,90,95,99 \
  --seed 42 \
  --save-result \
  --result-dir /tmp \
  --result-filename 07-office-baseline.json
08 · vllm bench serveopen-loop

Echte gesprekken · ShareGPT

Gesprekken uit ShareGPT V3, gemiddeld 228 tokens per beurt. De lengte varieert per gesprek.

dataset
sharegpt
rate (req/s)
0.3
prompts
250
burstiness
0.7

ttft p50/p95 · tokens/sec per gebruiker

250 prompts · seed 42view command →hide command ↑
docker exec vllm-bench vllm bench serve \
  --backend openai-chat \
  --base-url http://localhost:8000 \
  --endpoint /v1/chat/completions \
  --model ORG/MODEL \
  --tokenizer ORG/MODEL \
  --served-model-name SERVED_MODEL_NAME \
  --dataset-name sharegpt \
  --dataset-path /tmp/ShareGPT_V3.json \
  --num-prompts 250 \
  --request-rate 0.3 \
  --burstiness 0.7 \
  --percentile-metrics ttft,tpot,itl,e2el \
  --metric-percentiles 50,90,95,99 \
  --seed 42 \
  --save-result \
  --result-dir /tmp \
  --result-filename 08-sharegpt.json
09 · vllm bench serveopen-loop

Reasoning-workload

Lange denkstappen, 1k in en 4k uit, trage aankomstsnelheid van 0,2 omdat elke aanvraag veel decode-budget kost. Test of TTFT stabiel blijft.

dataset
random
input / output
1024 / 4096
rate (req/s)
0.2
prompts
50
burstiness
1

ttft p50 · volgehouden tokens/sec

50 prompts · seed 42view command →hide command ↑
docker exec vllm-bench vllm bench serve \
  --backend openai-chat \
  --base-url http://localhost:8000 \
  --endpoint /v1/chat/completions \
  --model ORG/MODEL \
  --tokenizer ORG/MODEL \
  --served-model-name SERVED_MODEL_NAME \
  --dataset-name random \
  --random-input-len 1024 \
  --random-output-len 4096 \
  --random-range-ratio 0.9 \
  --num-prompts 50 \
  --request-rate 0.2 \
  --burstiness 1.0 \
  --percentile-metrics ttft,tpot,itl,e2el \
  --metric-percentiles 50,90,95,99 \
  --seed 42 \
  --save-result \
  --result-dir /tmp \
  --result-filename 09-reasoning.json
10 · vllm bench serveopen-loop

Maandagochtendpiek

Random, 4000 in en 500 uit, aankomstsnelheid 1,5 per seconde met burstiness 1,0 en maximaal 25 parallel. Een zware, onafhankelijke requeststroom.

dataset
random
input / output
4000 / 500
rate (req/s)
1.5
prompts
300
burstiness
1
max parallel
25

ttft p95/p99 · wachtrijdiepte

300 prompts · seed 42view command →hide command ↑
docker exec vllm-bench vllm bench serve \
  --backend openai-chat \
  --base-url http://localhost:8000 \
  --endpoint /v1/chat/completions \
  --model ORG/MODEL \
  --tokenizer ORG/MODEL \
  --served-model-name SERVED_MODEL_NAME \
  --dataset-name random \
  --random-input-len 4000 \
  --random-output-len 500 \
  --random-range-ratio 0.9 \
  --num-prompts 300 \
  --request-rate 1.5 \
  --burstiness 1.0 \
  --max-concurrency 25 \
  --percentile-metrics ttft,tpot,itl,e2el \
  --metric-percentiles 50,90,95,99 \
  --seed 42 \
  --save-result \
  --result-dir /tmp \
  --result-filename 10-monday-peak.json
11 · vllm bench serveopen-loop

Capaciteit · rate sweep

Zes oplopende aankomstsnelheden, van 0,1 tot 1,0 aanvraag per seconde. Bij elke trede wordt gekeken of de p95 TTFT nog onder de grens blijft.

dataset
random
input / output
4000 / 500
rates (req/s)
0.1 · 0.2 · 0.3 · 0.5 · 0.7 · 1.0
prompts
100 · 100 · 100 · 125 · 175 · 250
burstiness
0.7

req/s onder p95 TTFT-grens

6 rates · seed 42view command →hide command ↑
# 0.1 req/s
docker exec vllm-bench vllm bench serve \
  --backend openai-chat \
  --base-url http://localhost:8000 \
  --endpoint /v1/chat/completions \
  --model ORG/MODEL \
  --tokenizer ORG/MODEL \
  --served-model-name SERVED_MODEL_NAME \
  --dataset-name random \
  --random-input-len 4000 \
  --random-output-len 500 \
  --random-range-ratio 0.9 \
  --num-prompts 100 \
  --request-rate 0.1 \
  --burstiness 0.7 \
  --percentile-metrics ttft,tpot,itl,e2el \
  --metric-percentiles 50,90,95,99 \
  --seed 42 \
  --save-result \
  --result-dir /tmp \
  --result-filename 11-rate-sweep-0.1.json

# 0.2 req/s
docker exec vllm-bench vllm bench serve \
  --backend openai-chat \
  --base-url http://localhost:8000 \
  --endpoint /v1/chat/completions \
  --model ORG/MODEL \
  --tokenizer ORG/MODEL \
  --served-model-name SERVED_MODEL_NAME \
  --dataset-name random \
  --random-input-len 4000 \
  --random-output-len 500 \
  --random-range-ratio 0.9 \
  --num-prompts 100 \
  --request-rate 0.2 \
  --burstiness 0.7 \
  --percentile-metrics ttft,tpot,itl,e2el \
  --metric-percentiles 50,90,95,99 \
  --seed 42 \
  --save-result \
  --result-dir /tmp \
  --result-filename 11-rate-sweep-0.2.json

# 0.3 req/s
docker exec vllm-bench vllm bench serve \
  --backend openai-chat \
  --base-url http://localhost:8000 \
  --endpoint /v1/chat/completions \
  --model ORG/MODEL \
  --tokenizer ORG/MODEL \
  --served-model-name SERVED_MODEL_NAME \
  --dataset-name random \
  --random-input-len 4000 \
  --random-output-len 500 \
  --random-range-ratio 0.9 \
  --num-prompts 100 \
  --request-rate 0.3 \
  --burstiness 0.7 \
  --percentile-metrics ttft,tpot,itl,e2el \
  --metric-percentiles 50,90,95,99 \
  --seed 42 \
  --save-result \
  --result-dir /tmp \
  --result-filename 11-rate-sweep-0.3.json

# 0.5 req/s
docker exec vllm-bench vllm bench serve \
  --backend openai-chat \
  --base-url http://localhost:8000 \
  --endpoint /v1/chat/completions \
  --model ORG/MODEL \
  --tokenizer ORG/MODEL \
  --served-model-name SERVED_MODEL_NAME \
  --dataset-name random \
  --random-input-len 4000 \
  --random-output-len 500 \
  --random-range-ratio 0.9 \
  --num-prompts 125 \
  --request-rate 0.5 \
  --burstiness 0.7 \
  --percentile-metrics ttft,tpot,itl,e2el \
  --metric-percentiles 50,90,95,99 \
  --seed 42 \
  --save-result \
  --result-dir /tmp \
  --result-filename 11-rate-sweep-0.5.json

# 0.7 req/s
docker exec vllm-bench vllm bench serve \
  --backend openai-chat \
  --base-url http://localhost:8000 \
  --endpoint /v1/chat/completions \
  --model ORG/MODEL \
  --tokenizer ORG/MODEL \
  --served-model-name SERVED_MODEL_NAME \
  --dataset-name random \
  --random-input-len 4000 \
  --random-output-len 500 \
  --random-range-ratio 0.9 \
  --num-prompts 175 \
  --request-rate 0.7 \
  --burstiness 0.7 \
  --percentile-metrics ttft,tpot,itl,e2el \
  --metric-percentiles 50,90,95,99 \
  --seed 42 \
  --save-result \
  --result-dir /tmp \
  --result-filename 11-rate-sweep-0.7.json

# 1.0 req/s
docker exec vllm-bench vllm bench serve \
  --backend openai-chat \
  --base-url http://localhost:8000 \
  --endpoint /v1/chat/completions \
  --model ORG/MODEL \
  --tokenizer ORG/MODEL \
  --served-model-name SERVED_MODEL_NAME \
  --dataset-name random \
  --random-input-len 4000 \
  --random-output-len 500 \
  --random-range-ratio 0.9 \
  --num-prompts 250 \
  --request-rate 1.0 \
  --burstiness 0.7 \
  --percentile-metrics ttft,tpot,itl,e2el \
  --metric-percentiles 50,90,95,99 \
  --seed 42 \
  --save-result \
  --result-dir /tmp \
  --result-filename 11-rate-sweep-1.0.json
GPU
NVIDIA DGX Spark
128 GB unified · GB10 Blackwell · NVFP4 native
Server
vLLM
exacte versie per run · prefix caching uit
Quant
BF16 · FP8 · NVFP4
elk model in beschikbare precisies
OS
Ubuntu 24.04
Docker image en driver staan in de runmetadata
Aggregatie
3 repeats · closed-loop
mean ± stddev per gemeten cel

De commando's worden deterministisch opgebouwd uit het versievaste contract en de metadata van elke run.

Start eerst een OpenAI-compatibele vLLM-server met de model- en serverconfig uit de runmetadata. Gebruik daarna het commando op de modelpagina. Voor test 08 moet ShareGPT V3 op /tmp/ShareGPT_V3.json staan; de andere open-looptests genereren synthetische random prompts.

Bij historische runs is het oorspronkelijke argv niet letterlijk opgeslagen. De gepubliceerde commando's zijn daarom gemarkeerde reconstructies uit contract en runmetadata. De bronlink bevat beide Git-revisies, zodat je precies ziet waarop de reconstructie rust.

  • Contract- en runbron vastgezet op een Git-revisie
  • Model-id, served name en toolversies uit runmetadata
  • Closed-loop: 3 repeats als mean ± stddev
  • Open-loop: seed 42, percentielen p50/p90/p95/p99 en minimaal 99% request success
  • Ruwe open-loopresultaten opgeslagen als JSON in /tmp
  • Geen prefix caching in de gepubliceerde runs

Een model dat je
graag in de suite ziet?

Stuur een Hugging Face-link of vLLM-configuratie. Als het model op de Spark past, kan ik het met dezelfde tests vergelijken.