main
md 1,518 lines 54 KB
Rendered Raw
1 # Benchmark CLI
2
3 This section guides you through running benchmark tests with the extensive datasets supported on vLLM.
4
5 It's a living document, updated as new features and datasets become available.
6
7 !!! tip
8 The benchmarks described on this page are mainly for evaluating specific vLLM features as well as regression testing.
9
10 For benchmarking production vLLM servers, we recommend [GuideLLM](https://github.com/vllm-project/guidellm), an established performance benchmarking framework with live progress updates and automatic report generation. It is also more flexible than `vllm bench serve` in terms of dataset loading, request formatting, and workload patterns.
11
12 ## Dataset Overview
13
14 <style>
15 th {
16 min-width: 0 !important;
17 }
18 </style>
19
20 | Dataset | Online | Offline | Data Path |
21 | ------- | ------ | ------- | --------- |
22 | ShareGPT | ✅ | ✅ | `wget https://huggingface.co/datasets/anon8231489123/ShareGPT_Vicuna_unfiltered/resolve/main/ShareGPT_V3_unfiltered_cleaned_split.json` |
23 | ShareGPT4V (Image) | ✅ | ✅ | `wget https://huggingface.co/datasets/Lin-Chen/ShareGPT4V/resolve/main/sharegpt4v_instruct_gpt4-vision_cap100k.json`<br>Note that the images need to be downloaded separately. For example, to download COCO's 2017 Train images:<br>`wget http://images.cocodataset.org/zips/train2017.zip` |
24 | ShareGPT4Video (Video) | ✅ | ✅ | `git clone https://huggingface.co/datasets/ShareGPT4Video/ShareGPT4Video` |
25 | BurstGPT | ✅ | ✅ | `wget https://github.com/HPMLL/BurstGPT/releases/download/v1.1/BurstGPT_without_fails_2.csv` |
26 | Sonnet (deprecated) | ✅ | ✅ | Local file: `benchmarks/sonnet.txt` |
27 | Random | ✅ | ✅ | `synthetic` |
28 | RandomMultiModal (Image/Video) | ✅ | ✅ | `synthetic` |
29 | RandomForReranking | ✅ | ✅ | `synthetic` |
30 | Prefix Repetition | ✅ | ✅ | `synthetic` |
31 | HuggingFace-VisionArena | ✅ | ✅ | `lmarena-ai/VisionArena-Chat` |
32 | HuggingFace-MMVU | ✅ | ✅ | `yale-nlp/MMVU` |
33 | HuggingFace-InstructCoder | ✅ | ✅ | `likaixin/InstructCoder` |
34 | HuggingFace-AIMO | ✅ | ✅ | `AI-MO/aimo-validation-aime`, `AI-MO/NuminaMath-1.5`, `AI-MO/NuminaMath-CoT` |
35 | HuggingFace-Other | ✅ | ✅ | `lmms-lab/LLaVA-OneVision-Data`, `Aeala/ShareGPT_Vicuna_unfiltered` |
36 | HuggingFace-MTBench | ✅ | ✅ | `philschmid/mt-bench` |
37 | HuggingFace-HumanEval | ✅ | ✅ | `openai/openai_humaneval` |
38 | HuggingFace-GSM8K | ✅ | ✅ | `openai/gsm8k` |
39 | HuggingFace-Blazedit | ✅ | ✅ | `vdaita/edit_5k_char`, `vdaita/edit_10k_char` |
40 | HuggingFace-ASR | ✅ | ✅ | `openslr/librispeech_asr`, `facebook/voxpopuli`, `LIUM/tedlium`, `edinburghcstr/ami`, `speechcolab/gigaspeech`, `kensho/spgispeech`, `ArtificialAnalysis/Earnings22-Cleaned-AA`, `D4nt3/esb-datasets-earnings22-validation-tiny-filtered` |
41 | Spec Bench | ✅ | ✅ | `wget https://raw.githubusercontent.com/hemingkx/Spec-Bench/refs/heads/main/data/spec_bench/question.jsonl` |
42 | SPEED-Bench | ✅ | ✅ | `curl -LsSf https://raw.githubusercontent.com/NVIDIA-NeMo/Skills/refs/heads/main/nemo_skills/dataset/speed-bench/prepare.py \| python3 -` |
43 | Custom | ✅ | ✅ | Local file: `data.jsonl` |
44 | Custom Audio | ✅ | ✅ | Local file: `audio_data.jsonl` |
45 | Custom Image | ✅ | ✅ | Local file: `image_data.jsonl` |
46
47 Legend:
48
49 - ✅ - supported
50 - 🟡 - Partial support
51 - 🚧 - to be supported
52
53 !!! note
54 HuggingFace dataset's `dataset-name` should be set to `hf`.
55 For local `dataset-path`, please set `hf-name` to its Hugging Face ID like
56
57 ```bash
58 --dataset-path /datasets/VisionArena-Chat/ --hf-name lmarena-ai/VisionArena-Chat
59 ```
60
61 ## Examples
62
63 ### 🚀 Online Benchmark
64
65 <details class="admonition abstract" markdown="1">
66 <summary>Show more</summary>
67
68 First start serving your model:
69
70 ```bash
71 vllm serve NousResearch/Hermes-3-Llama-3.1-8B
72 ```
73
74 Then run the benchmarking script:
75
76 ```bash
77 # download dataset
78 # wget https://huggingface.co/datasets/anon8231489123/ShareGPT_Vicuna_unfiltered/resolve/main/ShareGPT_V3_unfiltered_cleaned_split.json
79 vllm bench serve \
80 --backend vllm \
81 --model NousResearch/Hermes-3-Llama-3.1-8B \
82 --endpoint /v1/completions \
83 --dataset-name sharegpt \
84 --dataset-path <your data path>/ShareGPT_V3_unfiltered_cleaned_split.json \
85 --num-prompts 10
86 ```
87
88 If successful, you will see the following output:
89
90 ```text
91 ============ Serving Benchmark Result ============
92 Successful requests: 10
93 Benchmark duration (s): 5.78
94 Total input tokens: 1369
95 Total generated tokens: 2212
96 Request throughput (req/s): 1.73
97 Output token throughput (tok/s): 382.89
98 Total token throughput (tok/s): 619.85
99 ---------------Time to First Token----------------
100 Mean TTFT (ms): 71.54
101 Median TTFT (ms): 73.88
102 P99 TTFT (ms): 79.49
103 -----Time per Output Token (excl. 1st token)------
104 Mean TPOT (ms): 7.91
105 Median TPOT (ms): 7.96
106 P99 TPOT (ms): 8.03
107 ---------------Inter-token Latency----------------
108 Mean ITL (ms): 7.74
109 Median ITL (ms): 7.70
110 P99 ITL (ms): 8.39
111 ==================================================
112 ```
113
114 !!! warning
115 Repeating `vllm bench serve` against the same server can reuse prompts left
116 in the prefix cache and inflate throughput. This can affect any reproducible
117 dataset; the synthetic random dataset is reproducible for a fixed `--seed`,
118 which defaults to `0`. Prefix cache hits can also come from shared prefixes
119 within the run, so interpret cache metrics in the context of the workload.
120 If cache reuse is not intended, vary `--seed`, reset or restart the server,
121 or use `vllm bench sweep serve`, which resets server caches between runs.
122
123 #### Understanding the Latency Metrics
124
125 `vllm bench serve` measures latency at the benchmark client:
126
127 !!! note
128 Metric terminology is not standardized across benchmarking tools. When
129 comparing results, use the measurement points and formulas rather than the
130 metric names alone. This section explains how we refer to them in vLLM.
131
132 - **Time to first token (TTFT)** is the time from sending a request to receiving
133 its first streamed output.
134 - **Inter-token latency (ITL)** records the time between consecutive streamed
135 outputs. The reported ITL statistics aggregate these individual gaps across
136 all successful requests.
137 - **Time per output token (TPOT)** is calculated once per request, excluding the
138 first token, and then aggregated across requests:
139
140 $$
141 \text{TPOT} =
142 \frac{\text{end-to-end latency} - \text{TTFT}}
143 {\text{number of output tokens} - 1}
144 $$
145
146 With standard decoding, each streamed output usually contains one token, so ITL
147 and TPOT are typically similar.
148
149 With speculative decoding, one streamed output can contain multiple tokens,
150 such as several accepted draft tokens within a single engine step. ITL records
151 only the gaps between streamed outputs; it does not add zero-duration gaps for
152 tokens in the same output. TPOT instead amortizes the request's decoding time
153 over every output token.
154
155 ![Latency metrics with bundled tokens (light theme)](../assets/benchmarking/latency-metrics-speculative-decoding-light.svg#only-light)
156 ![Latency metrics with bundled tokens (dark theme)](../assets/benchmarking/latency-metrics-speculative-decoding-dark.svg#only-dark)
157
158 In this example, the benchmark observes two 40 ms ITL samples. The three tokens
159 in the second streamed output do not create additional ITL samples, so mean ITL
160 is 40 ms. TPOT is `(180 ms - 100 ms) / (5 - 1) = 20 ms/token`.
161
162 #### Results Visualization
163
164 The `--plot-timeline` and `--plot-dataset-stats` can be used to generate respectively the requests completion timeline and dataset prompt and output tokens statistics, which can be useful for debugging purpose or for deeper analysis.
165
166 ```bash
167 vllm bench serve \
168 --backend vllm \
169 --model meta-llama/Llama-3.1-8B-Instruct \
170 --endpoint /v1/completions \
171 --dataset-name sharegpt \
172 --dataset-path <your data path>/ShareGPT_V3_unfiltered_cleaned_split.json \
173 --num-prompts 100 \
174 --plot-timeline \
175 --timeline-itl-thresholds 2,5 \
176 --plot-dataset-stats \
177 --save-result
178 ```
179
180 ##### Interactive Timeline
181
182 The generated timeline is an interactive visualization in the form of an HTML file that can be rendered in most browsers. To customize the ITL color thresholds, one can use `--timeline-itl-thresholds` flag (default: 25ms, 50ms)
183
184 Example output:
185
186 <iframe src="../assets/contributing/vllm_bench_serve_timeline.html" width="100%" height="600" frameborder="0"></iframe>
187
188 ##### Dataset statistics
189
190 The generated figure shows the input prompt and output tokens distribution.
191
192 Example output: ![Dataset Statistics](../assets/contributing/vllm_bench_serve_dataset_stats.png)
193
194 #### Custom Dataset
195
196 If the dataset you want to benchmark is not supported yet in vLLM, even then you can benchmark on it using `CustomDataset`. At inference time, use the option `--dataset-name custom`. Your data needs to be in the `.jsonl` format and needs to have "prompt" field per entry, e.g., data.jsonl
197
198 ```json
199 {"prompt": "What is the capital of India?"}
200 {"prompt": "What is the capital of Iran?"}
201 {"prompt": "What is the capital of China?"}
202 ```
203
204 ```bash
205 # start server
206 vllm serve meta-llama/Llama-3.1-8B-Instruct
207 ```
208
209 ```bash
210 # run benchmarking script
211 vllm bench serve --port 9001 --save-result --save-detailed \
212 --backend vllm \
213 --model meta-llama/Llama-3.1-8B-Instruct \
214 --endpoint /v1/completions \
215 --dataset-name custom \
216 --dataset-path <path-to-your-data-jsonl> \
217 --skip-chat-template \
218 --num-prompts 80 \
219 --max-concurrency 1 \
220 --temperature=0.3 \
221 --top-p=0.75 \
222 --result-dir "./log/"
223 ```
224
225 You can skip applying chat template if your data already has it by using `--skip-chat-template`.
226
227 #### Custom Audio Dataset
228
229 If the audio dataset you want to benchmark is not supported yet in vLLM, then you can benchmark on it using `CustomAudioDataset`. At inference time, use the option `--dataset-name custom_audio`. Your data needs to be in the `.jsonl` format and needs to have "prompt" and "audio" fields per entry, e.g., `audio_data.jsonl`:
230
231 ```json
232 {"prompt": "What does this audio say?", "audio": "/path/to/audio_1.wav"}
233 {"prompt": "Transcribe the audio.", "audio": "/path/to/audio_2.wav"}
234 ```
235
236 - **Supported models:** The `CustomAudioDataset` class supports two types of audio models: ASR models (e.g. Whisper) which do not require a "prompt" field; and multimodal audio-text chat models (e.g. Qwen2-Audio). Since these model types require different arguments at inference, we are giving two examples.
237
238 - **Example 1: Whisper**
239
240 Whisper is a dedicated ASR encoder-decoder model, so it uses `--backend openai-audio` and `--endpoint /v1/audio/transcriptions`.
241
242 ```bash
243 # start server
244 vllm serve openai/whisper-tiny
245 ```
246
247 ```bash
248 vllm bench serve \
249 --model openai/whisper-tiny \
250 --backend openai-audio \
251 --endpoint /v1/audio/transcriptions \
252 --dataset-name custom_audio \
253 --dataset-path audio_data.jsonl \
254 --no-oversample \
255 --custom-output-len 256 \
256 --save-result \
257 --save-detailed \
258 --result-filename whisper_bench.json
259 ```
260
261 - **Example 2: Qwen2-Audio**
262
263 Qwen2-Audio is a multimodal chat model that can do ASR and speech analysis, so it uses `--backend openai-chat`, and `--endpoint /v1/chat/completions`. It also requires `--enable-multimodal-chat` to enable multimodal chat transformation.
264
265 ```bash
266 vllm bench serve \
267 --model Qwen/Qwen2-Audio-7B-Instruct \
268 --backend openai-chat \
269 --endpoint /v1/chat/completions \
270 --dataset-name custom_audio \
271 --dataset-path audio_data.jsonl \
272 --no-oversample \
273 --custom-output-len 256 \
274 --enable-multimodal-chat \
275 --save-result \
276 --save-detailed \
277 --result-filename qwen_bench.json
278 ```
279
280 #### Custom Image Dataset
281
282 If the image dataset you want to benchmark is not supported yet in vLLM, then you can benchmark on it using `CustomImageDataset`. At inference time, use the option `--dataset-name custom_image`. Your data needs to be in the `.jsonl` format and can use "prompt" and "image_files" fields per entry, e.g., `image_data.jsonl`:
283
284 ```json
285 {"prompt": "How many animals are present in the given image?", "image_files": ["/path/to/image/folder/horsepony.jpg"]}
286 {"prompt": "What colour is the bird shown in the image?", "image_files": ["/path/to/image/folder/flycatcher.jpeg"]}
287 ```
288
289 Every image listed in "image_files" is added to the request in the listed order after the prompt text. To preserve an interleaved order of text and images, use a "content" field with OpenAI-compatible content parts:
290
291 ```json
292 {"content": [{"type": "text", "text": "Compare "}, {"type": "image", "image": "/path/to/image/folder/chart_a.png"}, {"type": "text", "text": " with "}, {"type": "image_url", "image_url": {"url": "/path/to/image/folder/chart_b.png"}}]}
293 ```
294
295 The "image" shorthand accepts the same values as "image_files". The "image_url" field accepts either an OpenAI-style object with a "url" field or a URL string.
296
297 By default, image references are sent to the serving endpoint as provided, with local image paths converted to `file://` URLs.
298
299 If the benchmark client should load local and HTTP(S) images before sending requests, pass `--custom-ensure-client-side-data` to encode them as base64 data URLs on the client side.
300
301 Existing `data:image/...` URLs are already self-contained and are kept unchanged.
302
303 ```bash
304 # need a model with vision capability here
305 vllm serve Qwen/Qwen2-VL-7B-Instruct
306 ```
307
308 ```bash
309 # run benchmarking script
310 vllm bench serve --save-result --save-detailed \
311 --backend openai-chat \
312 --model Qwen/Qwen2-VL-7B-Instruct \
313 --endpoint /v1/chat/completions \
314 --dataset-name custom_image \
315 --dataset-path <path-to-your-image-data-jsonl> \
316 --custom-ensure-client-side-data
317 ```
318
319 Note that we need to use the `openai-chat` backend and `/v1/chat/completions` endpoint for multimodal inputs.
320
321 #### VisionArena Benchmark for Vision Language Models
322
323 ```bash
324 # need a model with vision capability here
325 vllm serve Qwen/Qwen2-VL-7B-Instruct
326 ```
327
328 ```bash
329 vllm bench serve \
330 --backend openai-chat \
331 --model Qwen/Qwen2-VL-7B-Instruct \
332 --endpoint /v1/chat/completions \
333 --dataset-name hf \
334 --dataset-path lmarena-ai/VisionArena-Chat \
335 --hf-split train \
336 --num-prompts 1000
337 ```
338
339 #### InstructCoder Benchmark with Speculative Decoding
340
341 ``` bash
342 vllm serve meta-llama/Meta-Llama-3-8B-Instruct \
343 --speculative-config $'{"method": "ngram",
344 "num_speculative_tokens": 5, "prompt_lookup_max": 5,
345 "prompt_lookup_min": 2}'
346 ```
347
348 ``` bash
349 vllm bench serve \
350 --model meta-llama/Meta-Llama-3-8B-Instruct \
351 --dataset-name hf \
352 --dataset-path likaixin/InstructCoder \
353 --num-prompts 2048
354 ```
355
356 #### Spec Bench Benchmark with Speculative Decoding
357
358 ``` bash
359 vllm serve meta-llama/Meta-Llama-3-8B-Instruct \
360 --speculative-config $'{"method": "ngram",
361 "num_speculative_tokens": 5, "prompt_lookup_max": 5,
362 "prompt_lookup_min": 2}'
363 ```
364
365 [SpecBench dataset](https://github.com/hemingkx/Spec-Bench)
366
367 Run all categories:
368
369 ``` bash
370 # Download the dataset using:
371 # wget https://raw.githubusercontent.com/hemingkx/Spec-Bench/refs/heads/main/data/spec_bench/question.jsonl
372
373 vllm bench serve \
374 --model meta-llama/Meta-Llama-3-8B-Instruct \
375 --dataset-name spec_bench \
376 --dataset-path "<YOUR_DOWNLOADED_PATH>/data/spec_bench/question.jsonl" \
377 --num-prompts -1
378 ```
379
380 Available categories include `[writing, roleplay, reasoning, math, coding, extraction, stem, humanities, translation, summarization, qa, math_reasoning, rag]`.
381
382 Run only a specific category like "summarization":
383
384 ``` bash
385 vllm bench serve \
386 --model meta-llama/Meta-Llama-3-8B-Instruct \
387 --dataset-name spec_bench \
388 --dataset-path "<YOUR_DOWNLOADED_PATH>/data/spec_bench/question.jsonl" \
389 --num-prompts -1 \
390 --spec-bench-category "summarization"
391 ```
392
393 #### SPEED-Bench Benchmark with Speculative Decoding
394
395 [SPEED-Bench](https://huggingface.co/datasets/nvidia/SPEED-Bench) is a unified and diverse dataset for speculative decoding, supporting acceptance rate and length measurements using the Qualitative split and throughput measurements using the Throughput splits in 5 configuration of input sequence length (1k, 2k, 8k, 16k, 32k).
396
397 !!! note
398 This dataset is governed by the [NVIDIA Evaluation Dataset License Agreement](https://huggingface.co/datasets/nvidia/SPEED-Bench/blob/main/License.pdf). For each dataset a user elects to use, the user is responsible for checking if the dataset license is fit for the intended purpose. The `prepare.py` script automatically fetches data from all the source datasets.
399
400 First, download the dataset to a folder, using this one liner:
401
402 ```bash
403 curl -LsSf https://raw.githubusercontent.com/NVIDIA-NeMo/Skills/refs/heads/main/nemo_skills/dataset/speed-bench/prepare.py | python3 -
404 ```
405
406 The command supports also the following arguments:
407
408 - `--config`: download only a subset of the dataset: `qualitative`, `throughput_1k`, `throughput_2k`, `throughput_8k`, `throughput_16k` and `throughput_32k`. By default, it will download all subsets.
409 - `--output_dir`: download to a specified folder. By default, it will download to the current directory.
410
411 Start a server with speculative decoding:
412
413 ```bash
414 vllm serve meta-llama/Llama-3.3-70B-Instruct \
415 --speculative-config $'{"method": "eagle3",
416 "num_speculative_tokens": 3,
417 "model": "nvidia/Llama-3.3-70B-Instruct-Eagle3"}'
418 ```
419
420 Run all categories in the Qualitative split:
421
422 ```bash
423 vllm bench serve \
424 --model meta-llama/Llama-3.3-70B-Instruct \
425 --dataset-name speed_bench \
426 --dataset-path "<YOUR_DOWNLOADED_PATH>/data/speed_bench" \
427 --num-prompts -1
428 ```
429
430 Available categories include `[writing, roleplay, reasoning, math, coding, stem, humanities, multilingual, summarization, qa, rag]`.
431
432 Run only a specific category like "multilingual":
433
434 ```bash
435 vllm bench serve \
436 --model meta-llama/Llama-3.3-70B-Instruct \
437 --dataset-name speed_bench \
438 --dataset-path "<YOUR_DOWNLOADED_PATH>/data/speed_bench" \
439 --num-prompts -1 \
440 --speed-bench-category "multilingual"
441 ```
442
443 Run all categories in the Throughput split (2k ISL):
444
445 ```bash
446 vllm bench serve \
447 --model meta-llama/Llama-3.3-70B-Instruct \
448 --dataset-name speed_bench \
449 --speed-bench-dataset-subset throughput_2k \
450 --dataset-path "<YOUR_DOWNLOADED_PATH>/data/speed_bench/" \
451 --num-prompts -1
452 ```
453
454 Available categories include `[high_entropy, mixed, low_entropy]`, where high entropy data contains unstructured data such as creative writing while low entropy data contains more structured data such as coding, more details are in the dataset card.
455
456 #### BFCL (Tool-Calling) Benchmark
457
458 The Berkeley Function Calling Leaderboard (BFCL) dataset measures serving
459 latency and throughput on realistic tool-calling traffic. Each request
460 carries a per-sample `tools` schema and chat history, so the server must
461 expose `/v1/chat/completions` with an auto-tool-choice parser enabled.
462 The benchmark client always uses the `openai-chat` backend.
463
464 Start a tool-parser-enabled server, then run the bench. For example, with
465 `gpt-oss-20b`:
466
467 ```bash
468 # Server
469 vllm serve openai/gpt-oss-20b \
470 --enable-auto-tool-choice \
471 --tool-call-parser openai \
472 --reasoning-parser openai_gptoss
473
474 # Client
475 vllm bench serve \
476 --backend openai-chat \
477 --endpoint /v1/chat/completions \
478 --model openai/gpt-oss-20b \
479 --dataset-name hf \
480 --dataset-path gorilla-llm/Berkeley-Function-Calling-Leaderboard \
481 --bfcl-categories simple,live_simple,multiple \
482 --num-prompts 200
483 ```
484
485 `--bfcl-categories` is a comma-separated list of BFCL v3 category names
486 (without the `BFCL_v3_` prefix or `.json` suffix). Defaults to
487 `simple,live_simple,multiple`. Other supported non-multi-turn categories
488 include `parallel`, `live_parallel`, `parallel_multiple`,
489 `live_parallel_multiple`, `irrelevance`, `live_irrelevance`,
490 `live_relevance`, `java`, `javascript`, and `rest`. Multi-turn categories
491 are not yet supported.
492
493 The dataset class normalizes BFCL's loose schema dialect (`dict` →
494 `object`, `float` → `number`, `tuple` → `array`, `any` → `string`) so
495 modern grammar backends accept the translated tool definitions.
496
497 #### Other HuggingFaceDataset Examples
498
499 ```bash
500 vllm serve Qwen/Qwen2-VL-7B-Instruct
501 ```
502
503 `lmms-lab/LLaVA-OneVision-Data`:
504
505 ```bash
506 vllm bench serve \
507 --backend openai-chat \
508 --model Qwen/Qwen2-VL-7B-Instruct \
509 --endpoint /v1/chat/completions \
510 --dataset-name hf \
511 --dataset-path lmms-lab/LLaVA-OneVision-Data \
512 --hf-split train \
513 --hf-subset "chart2text(cauldron)" \
514 --num-prompts 10
515 ```
516
517 `Aeala/ShareGPT_Vicuna_unfiltered`:
518
519 ```bash
520 vllm bench serve \
521 --backend openai-chat \
522 --model Qwen/Qwen2-VL-7B-Instruct \
523 --endpoint /v1/chat/completions \
524 --dataset-name hf \
525 --dataset-path Aeala/ShareGPT_Vicuna_unfiltered \
526 --hf-split train \
527 --num-prompts 10
528 ```
529
530 `AI-MO/aimo-validation-aime`:
531
532 ``` bash
533 vllm bench serve \
534 --model Qwen/QwQ-32B \
535 --dataset-name hf \
536 --dataset-path AI-MO/aimo-validation-aime \
537 --num-prompts 10 \
538 --seed 42
539 ```
540
541 `philschmid/mt-bench`:
542
543 ``` bash
544 vllm bench serve \
545 --model Qwen/QwQ-32B \
546 --dataset-name hf \
547 --dataset-path philschmid/mt-bench \
548 --num-prompts 80
549 ```
550
551 `openai/openai_humaneval`:
552
553 ``` bash
554 vllm bench serve \
555 --model NousResearch/Hermes-3-Llama-3.1-8B \
556 --dataset-name hf \
557 --dataset-path openai/openai_humaneval \
558 --num-prompts 80
559 ```
560
561 `openai/gsm8k`:
562
563 ``` bash
564 vllm bench serve \
565 --model NousResearch/Hermes-3-Llama-3.1-8B \
566 --dataset-name hf \
567 --dataset-path openai/gsm8k \
568 --num-prompts 80
569 ```
570
571 `vdaita/edit_5k_char` or `vdaita/edit_10k_char`:
572
573 ``` bash
574 vllm bench serve \
575 --model Qwen/QwQ-32B \
576 --dataset-name hf \
577 --dataset-path vdaita/edit_5k_char \
578 --num-prompts 90 \
579 --blazedit-min-distance 0.01 \
580 --blazedit-max-distance 0.99
581 ```
582
583 `openslr/librispeech_asr`, `facebook/voxpopuli`, `LIUM/tedlium`, `edinburghcstr/ami`, `speechcolab/gigaspeech`, `kensho/spgispeech`, `ArtificialAnalysis/Earnings22-Cleaned-AA`, `D4nt3/esb-datasets-earnings22-validation-tiny-filtered`
584
585 ```bash
586 vllm bench serve \
587 --model openai/whisper-large-v3-turbo \
588 --backend openai-audio \
589 --dataset-name hf \
590 --dataset-path facebook/voxpopuli --hf-subset en --hf-split test --no-stream --trust-remote-code \
591 --num-prompts 99999999 \
592 --no-oversample \
593 --endpoint /v1/audio/transcriptions \
594 --ready-check-timeout-sec 600 \
595 --save-result \
596 --max-concurrency 512
597 ```
598
599 #### Responses API Benchmark
600
601 The `openai-responses` backend benchmarks vLLM's
602 [Responses API](../serving/online_serving/openai_compatible_server.md#responses-api)
603 directly, instead of routing the same workload through `/v1/chat/completions`.
604
605 ```bash
606 # Server
607 vllm serve openai/gpt-oss-20b
608
609 # Client
610 vllm bench serve \
611 --backend openai-responses \
612 --endpoint /v1/responses \
613 --model openai/gpt-oss-20b \
614 --dataset-name random \
615 --random-input-len 1024 \
616 --random-output-len 1024 \
617 --num-prompts 200
618 ```
619
620 Reasoning deltas (`response.reasoning_text.delta`) count towards TTFT and ITL,
621 because the server is already decoding tokens when it emits them. Only output
622 text (`response.output_text.delta`) is collected as the generated text, which
623 matches how the `openai-chat` backend treats `DeltaMessage.reasoning`. End-to-end
624 latency stops at the last token event, so `latency - ttft` equals `sum(itl)` and
625 TPOT is comparable with the other endpoints. The input and output token counts
626 come from the usage block on `response.completed`, which is still required: a
627 stream that ends without a terminal event is reported as a failed request.
628
629 The backend measures one streamed text-generation request per prompt. Built-in
630 tools, MCP, and multi-turn state via `previous_response_id` are out of scope.
631 All sampling parameter flags are supported except `--min-p`, which the
632 Responses API does not accept.
633
634 !!! warning
635 Do not pass `--extra-body '{"include_reasoning": false}'` when benchmarking
636 a reasoning model. The server still generates reasoning tokens but emits no
637 events for them, so the whole reasoning phase is absorbed into TTFT.
638
639 #### Running With Sampling Parameters
640
641 When using OpenAI-compatible backends such as `vllm`, optional sampling
642 parameters can be specified. Example client command:
643
644 ```bash
645 vllm bench serve \
646 --backend vllm \
647 --model NousResearch/Hermes-3-Llama-3.1-8B \
648 --endpoint /v1/completions \
649 --dataset-name sharegpt \
650 --dataset-path <your data path>/ShareGPT_V3_unfiltered_cleaned_split.json \
651 --top-k 10 \
652 --top-p 0.9 \
653 --temperature 0.5 \
654 --num-prompts 10
655 ```
656
657 #### Running With Ramp-Up Request Rate
658
659 The benchmark tool also supports ramping up the request rate over the
660 duration of the benchmark run. This can be useful for stress testing the
661 server or finding the maximum throughput that it can handle, given some latency budget.
662
663 Two ramp-up strategies are supported:
664
665 - `linear`: Increases the request rate linearly from a start value to an end value.
666 - `exponential`: Increases the request rate exponentially.
667
668 The following arguments can be used to control the ramp-up:
669
670 - `--ramp-up-strategy`: The ramp-up strategy to use (`linear` or `exponential`).
671 - `--ramp-up-start-rps`: The request rate at the beginning of the benchmark.
672 - `--ramp-up-end-rps`: The request rate at the end of the benchmark.
673
674 #### Probe Requests
675
676 The benchmark tool also supports sending probe requests alongside the main
677 workload. This can be useful for measuring how the main workload affects
678 unrelated traffic sharing the server, e.g. a few requests with large images
679 stalling a concurrent lightweight request while their multimodal preprocessing
680 occupies the frontend.
681
682 Setting `--probe-request-rate` to a positive value sends single-token text-only
683 probe requests at that rate (requests per second) alongside the main workload.
684 Probes bypass `--max-concurrency` and their latency is reported separately, so
685 the probe percentiles directly measure the interference that the main workload
686 inflicts on unrelated requests.
687
688 ```bash
689 vllm bench serve \
690 --model Qwen/Qwen2.5-VL-3B-Instruct \
691 --backend openai-chat \
692 --endpoint /v1/chat/completions \
693 --dataset-name random-mm \
694 --random-mm-bucket-config '{(2048, 2048, 1): 1.0}' \
695 --request-rate 4 \
696 --probe-request-rate 20
697 ```
698
699 #### Load Pattern Configuration
700
701 vLLM's benchmark serving script provides sophisticated load pattern simulation capabilities through three key parameters that control request generation and concurrency behavior:
702
703 ##### Load Pattern Control Parameters
704
705 - `--request-rate`: Controls the target request generation rate (requests per second). Set to `inf` for maximum throughput testing or finite values for controlled load simulation.
706 - `--burstiness`: Controls traffic variability using a Gamma distribution (range: > 0). Lower values create bursty traffic, higher values create uniform traffic.
707 - `--max-concurrency`: Limits concurrent outstanding requests. If this argument is not provided, concurrency is unlimited. Set a value to simulate backpressure. When set, include `client_queue_time` in `--percentile-metrics` to report time spent waiting for the benchmark client's concurrency limit. With a finite `--request-rate`, `e2el_including_client_queue` reports schedule-relative end-to-end latency; it is omitted for `--request-rate=inf`, where all requests arrive at benchmark start.
708
709 These parameters work together to create realistic load patterns with carefully chosen defaults. The `--request-rate` parameter defaults to `inf` (infinite), which sends all requests immediately for maximum throughput testing. When set to finite values, it uses either a Poisson process (default `--burstiness=1.0`) or Gamma distribution for realistic request timing. The `--burstiness` parameter only takes effect when `--request-rate` is not infinite - a value of 1.0 creates natural Poisson traffic, while lower values (0.1-0.5) create bursty patterns and higher values (2.0-5.0) create uniform spacing. The `--max-concurrency` parameter defaults to `None` (unlimited) but can be set to simulate real-world constraints where a load balancer or API gateway limits concurrent connections. When combined, these parameters allow you to simulate everything from unrestricted stress testing (`--request-rate=inf`) to production-like scenarios with realistic arrival patterns and resource constraints.
710
711 The `--burstiness` parameter mathematically controls request arrival patterns using a Gamma distribution where:
712
713 - Shape parameter: `burstiness` value
714 - Coefficient of Variation (CV): $\frac{1}{\sqrt{burstiness}}$
715 - Traffic characteristics:
716 - `burstiness = 0.1`: Highly bursty traffic (CV ≈ 3.16) - stress testing
717 - `burstiness = 1.0`: Natural Poisson traffic (CV = 1.0) - realistic simulation
718 - `burstiness = 5.0`: Uniform traffic (CV ≈ 0.45) - controlled load testing
719
720 ![Load Pattern Examples](../assets/contributing/load-pattern-examples.png)
721
722 *Figure: Load pattern examples for each use case. Top row: Request arrival timelines showing cumulative requests over time. Bottom row: Inter-arrival time distributions showing traffic variability patterns. Each column represents a different use case with its specific parameter settings and resulting traffic characteristics.*
723
724 Load Pattern Recommendations by Use Case:
725
726 | Use Case | Burstiness | Request Rate | Max Concurrency | Description |
727 | --- | --- | --- | --- | --- |
728 | Maximum Throughput | N/A | Infinite | Limited | **Most common**: Simulates load balancer/gateway limits with unlimited user demand |
729 | Realistic Testing | 1.0 | Moderate (5-20) | Infinite | Natural Poisson traffic patterns for baseline performance |
730 | Stress Testing | 0.1-0.5 | High (20-100) | Infinite | Challenging burst patterns to test resilience |
731 | Latency Profiling | 2.0-5.0 | Low (1-10) | Infinite | Uniform load for consistent timing analysis |
732 | Capacity Planning | 1.0 | Variable | Limited | Test resource limits with realistic constraints |
733 | SLA Validation | 1.0 | Target rate | SLA limit | Production-like constraints for compliance testing |
734
735 These load patterns help evaluate different aspects of your vLLM deployment, from basic performance characteristics to resilience under challenging traffic conditions.
736
737 The **Maximum Throughput** pattern (`--request-rate=inf --max-concurrency=<limit>`) is the most commonly used configuration for production benchmarking. This simulates real-world deployment architectures where:
738
739 - Users send requests as fast as they can (infinite rate)
740 - A load balancer or API gateway controls the maximum concurrent connections
741 - The system operates at its concurrency limit, revealing true throughput capacity
742 - `--burstiness` has no effect since request timing is not controlled when rate is infinite
743
744 This pattern helps determine optimal concurrency settings for your production load balancer configuration.
745
746 To effectively configure load patterns, especially for **Capacity Planning** and **SLA Validation** use cases, you need to understand your system's resource limits. During startup, vLLM reports KV cache configuration that directly impacts your load testing parameters:
747
748 ```text
749 GPU KV cache size: 15,728,640 tokens
750 Maximum concurrency for 8,192 tokens per request: 1920
751 ```
752
753 Where:
754
755 - GPU KV cache size: Total tokens that can be cached across all concurrent requests
756 - Maximum concurrency: Theoretical maximum concurrent requests for the given `max_model_len`
757 - Calculation: `max_concurrency = kv_cache_size / max_model_len`
758
759 Using KV cache metrics for load pattern configuration:
760
761 - For Capacity Planning: Set `--max-concurrency` to 80-90% of the reported maximum to test realistic resource constraints
762 - For SLA Validation: Use the reported maximum as your SLA limit to ensure compliance testing matches production capacity
763 - For Realistic Testing: Monitor memory usage when approaching theoretical limits to understand sustainable request rates
764 - Request rate guidance: Use the KV cache size to estimate sustainable request rates for your specific workload and sequence lengths
765
766 </details>
767
768 ### 📈 Offline Throughput Benchmark
769
770 <details class="admonition abstract" markdown="1">
771 <summary>Show more</summary>
772
773 ```bash
774 vllm bench throughput \
775 --model NousResearch/Hermes-3-Llama-3.1-8B \
776 --dataset-name sonnet \
777 --dataset-path vllm/benchmarks/sonnet.txt \
778 --num-prompts 10
779 ```
780
781 If successful, you will see the following output
782
783 ```text
784 Throughput: 7.15 requests/s, 4656.00 total tokens/s, 1072.15 output tokens/s
785 Total num prompt tokens: 5014
786 Total num output tokens: 1500
787 ```
788
789 #### VisionArena Benchmark for Vision Language Models
790
791 ```bash
792 vllm bench throughput \
793 --model Qwen/Qwen2-VL-7B-Instruct \
794 --backend vllm-chat \
795 --dataset-name hf \
796 --dataset-path lmarena-ai/VisionArena-Chat \
797 --num-prompts 1000 \
798 --hf-split train
799 ```
800
801 The `num prompt tokens` now includes image token counts
802
803 ```text
804 Throughput: 2.55 requests/s, 4036.92 total tokens/s, 326.90 output tokens/s
805 Total num prompt tokens: 14527
806 Total num output tokens: 1280
807 ```
808
809 #### InstructCoder Benchmark with Speculative Decoding
810
811 ``` bash
812 VLLM_WORKER_MULTIPROC_METHOD=spawn \
813 vllm bench throughput \
814 --dataset-name=hf \
815 --dataset-path=likaixin/InstructCoder \
816 --model=meta-llama/Meta-Llama-3-8B-Instruct \
817 --input-len=1000 \
818 --output-len=100 \
819 --num-prompts=2048 \
820 --async-engine \
821 --speculative-config $'{"method": "ngram",
822 "num_speculative_tokens": 5, "prompt_lookup_max": 5,
823 "prompt_lookup_min": 2}'
824 ```
825
826 ```text
827 Throughput: 104.77 requests/s, 23836.22 total tokens/s, 10477.10 output tokens/s
828 Total num prompt tokens: 261136
829 Total num output tokens: 204800
830 ```
831
832 #### Other HuggingFaceDataset Examples
833
834 `lmms-lab/LLaVA-OneVision-Data`:
835
836 ```bash
837 vllm bench throughput \
838 --model Qwen/Qwen2-VL-7B-Instruct \
839 --backend vllm-chat \
840 --dataset-name hf \
841 --dataset-path lmms-lab/LLaVA-OneVision-Data \
842 --hf-split train \
843 --hf-subset "chart2text(cauldron)" \
844 --num-prompts 10
845 ```
846
847 `Aeala/ShareGPT_Vicuna_unfiltered`:
848
849 ```bash
850 vllm bench throughput \
851 --model Qwen/Qwen2-VL-7B-Instruct \
852 --backend vllm-chat \
853 --dataset-name hf \
854 --dataset-path Aeala/ShareGPT_Vicuna_unfiltered \
855 --hf-split train \
856 --num-prompts 10
857 ```
858
859 `AI-MO/aimo-validation-aime`:
860
861 ```bash
862 vllm bench throughput \
863 --model Qwen/QwQ-32B \
864 --backend vllm \
865 --dataset-name hf \
866 --dataset-path AI-MO/aimo-validation-aime \
867 --hf-split train \
868 --num-prompts 10
869 ```
870
871 Benchmark with LoRA adapters:
872
873 ``` bash
874 # download dataset
875 # wget https://huggingface.co/datasets/anon8231489123/ShareGPT_Vicuna_unfiltered/resolve/main/ShareGPT_V3_unfiltered_cleaned_split.json
876 vllm bench throughput \
877 --model meta-llama/Llama-2-7b-hf \
878 --backend vllm \
879 --dataset_path <your data path>/ShareGPT_V3_unfiltered_cleaned_split.json \
880 --dataset_name sharegpt \
881 --num-prompts 10 \
882 --max-loras 2 \
883 --max-lora-rank 8 \
884 --enable-lora \
885 --lora-path yard1/llama-2-7b-sql-lora-test
886 ```
887
888 #### Synthetic Random Multimodal (random-mm)
889
890 Generate synthetic multimodal inputs for offline throughput testing without external datasets.
891 Use `--backend vllm-chat` so that image tokens are counted correctly.
892
893 ```bash
894 vllm bench throughput \
895 --model Qwen/Qwen2-VL-7B-Instruct \
896 --backend vllm-chat \
897 --dataset-name random-mm \
898 --num-prompts 100 \
899 --random-input-len 300 \
900 --random-output-len 40 \
901 --random-mm-base-items-per-request 2 \
902 --random-mm-limit-mm-per-prompt '{"image": 3, "video": 0}' \
903 --random-mm-bucket-config '{(256, 256, 1): 0.7, (720, 1280, 1): 0.3}'
904 ```
905
906 </details>
907
908 ### 🛠️ Structured Output Benchmark
909
910 <details class="admonition abstract" markdown="1">
911 <summary>Show more</summary>
912
913 Benchmark the performance of structured output generation (JSON, grammar, regex).
914
915 #### Server Setup
916
917 ```bash
918 vllm serve NousResearch/Hermes-3-Llama-3.1-8B
919 ```
920
921 #### JSON Schema Benchmark
922
923 ```bash
924 python3 benchmarks/benchmark_serving_structured_output.py \
925 --backend vllm \
926 --model NousResearch/Hermes-3-Llama-3.1-8B \
927 --dataset json \
928 --structured-output-ratio 1.0 \
929 --request-rate 10 \
930 --num-prompts 1000
931 ```
932
933 #### Grammar-based Generation Benchmark
934
935 ```bash
936 python3 benchmarks/benchmark_serving_structured_output.py \
937 --backend vllm \
938 --model NousResearch/Hermes-3-Llama-3.1-8B \
939 --dataset grammar \
940 --structure-type grammar \
941 --request-rate 10 \
942 --num-prompts 1000
943 ```
944
945 #### Regex-based Generation Benchmark
946
947 ```bash
948 python3 benchmarks/benchmark_serving_structured_output.py \
949 --backend vllm \
950 --model NousResearch/Hermes-3-Llama-3.1-8B \
951 --dataset regex \
952 --request-rate 10 \
953 --num-prompts 1000
954 ```
955
956 #### Choice-based Generation Benchmark
957
958 ```bash
959 python3 benchmarks/benchmark_serving_structured_output.py \
960 --backend vllm \
961 --model NousResearch/Hermes-3-Llama-3.1-8B \
962 --dataset choice \
963 --request-rate 10 \
964 --num-prompts 1000
965 ```
966
967 #### XGrammar Benchmark Dataset
968
969 ```bash
970 python3 benchmarks/benchmark_serving_structured_output.py \
971 --backend vllm \
972 --model NousResearch/Hermes-3-Llama-3.1-8B \
973 --dataset xgrammar_bench \
974 --request-rate 10 \
975 --num-prompts 1000
976 ```
977
978 </details>
979
980 ### 📚 Long Document QA Benchmark
981
982 <details class="admonition abstract" markdown="1">
983 <summary>Show more</summary>
984
985 Benchmark the performance of long document question-answering with prefix caching.
986
987 #### Basic Long Document QA Test
988
989 ```bash
990 python3 benchmarks/benchmark_long_document_qa_throughput.py \
991 --model meta-llama/Llama-2-7b-chat-hf \
992 --enable-prefix-caching \
993 --num-documents 16 \
994 --document-length 2000 \
995 --output-len 50 \
996 --repeat-count 5
997 ```
998
999 #### Different Repeat Modes
1000
1001 ```bash
1002 # Random mode (default) - shuffle prompts randomly
1003 python3 benchmarks/benchmark_long_document_qa_throughput.py \
1004 --model meta-llama/Llama-2-7b-chat-hf \
1005 --enable-prefix-caching \
1006 --num-documents 8 \
1007 --document-length 3000 \
1008 --repeat-count 3 \
1009 --repeat-mode random
1010
1011 # Tile mode - repeat entire prompt list in sequence
1012 python3 benchmarks/benchmark_long_document_qa_throughput.py \
1013 --model meta-llama/Llama-2-7b-chat-hf \
1014 --enable-prefix-caching \
1015 --num-documents 8 \
1016 --document-length 3000 \
1017 --repeat-count 3 \
1018 --repeat-mode tile
1019
1020 # Interleave mode - repeat each prompt consecutively
1021 python3 benchmarks/benchmark_long_document_qa_throughput.py \
1022 --model meta-llama/Llama-2-7b-chat-hf \
1023 --enable-prefix-caching \
1024 --num-documents 8 \
1025 --document-length 3000 \
1026 --repeat-count 3 \
1027 --repeat-mode interleave
1028 ```
1029
1030 </details>
1031
1032 ### 🗂️ Prefix Caching Benchmark
1033
1034 <details class="admonition abstract" markdown="1">
1035 <summary>Show more</summary>
1036
1037 Benchmark the efficiency of automatic prefix caching.
1038
1039 #### Fixed Prompt with Prefix Caching
1040
1041 ```bash
1042 python3 benchmarks/benchmark_prefix_caching.py \
1043 --model meta-llama/Llama-2-7b-chat-hf \
1044 --enable-prefix-caching \
1045 --num-prompts 1 \
1046 --repeat-count 100 \
1047 --input-length-range 128:256
1048 ```
1049
1050 #### ShareGPT Dataset with Prefix Caching
1051
1052 ```bash
1053 # download dataset
1054 # wget https://huggingface.co/datasets/anon8231489123/ShareGPT_Vicuna_unfiltered/resolve/main/ShareGPT_V3_unfiltered_cleaned_split.json
1055
1056 python3 benchmarks/benchmark_prefix_caching.py \
1057 --model meta-llama/Llama-2-7b-chat-hf \
1058 --dataset-path /path/ShareGPT_V3_unfiltered_cleaned_split.json \
1059 --enable-prefix-caching \
1060 --num-prompts 20 \
1061 --repeat-count 5 \
1062 --input-length-range 128:256
1063 ```
1064
1065 ##### Prefix Repetition Dataset
1066
1067 ```bash
1068 vllm bench serve \
1069 --backend openai \
1070 --model meta-llama/Llama-2-7b-chat-hf \
1071 --dataset-name prefix_repetition \
1072 --num-prompts 100 \
1073 --prefix-repetition-prefix-len 512 \
1074 --prefix-repetition-suffix-len 128 \
1075 --prefix-repetition-num-prefixes 5 \
1076 --prefix-repetition-output-len 128
1077 ```
1078
1079 </details>
1080
1081 ### Replay Timed Traces
1082
1083 <details class="admonition abstract" markdown="1">
1084 <summary>Show more</summary>
1085
1086 Example of how to run traces which have timing information
1087 with them.
1088
1089 #### Running MoonshotAI traces
1090
1091 Start the server:
1092
1093 ```bash
1094 vllm serve Qwen/Qwen3.5-2B \
1095 --host 127.0.0.1 --port 8000
1096 ```
1097
1098 Run the benchmark:
1099
1100 ```bash
1101 # Download an example trace
1102 # curl -L -o conversation_trace.jsonl \
1103 #https://raw.githubusercontent.com/kvcache-ai/Mooncake/main/FAST25-release/traces/conversation_trace.jsonl
1104
1105 vllm bench serve --model Qwen/Qwen3.5-2B \
1106 --dataset-name=timed_trace --num-prompts 100 --host 127.0.0.1 \
1107 --port 8000 --dataset-path ./conversation_trace.jsonl \
1108 --ignore-eos --self-timed --timed-trace-chunk-hash-size 512 \
1109 --timed-trace-sec-multiplier 0.001
1110 ```
1111
1112 This will replay the first 100 lines from the trace file `conversation.jsonl`.
1113
1114 </details>
1115
1116 ### 🧪 Hashing Benchmarks
1117
1118 <details class="admonition abstract" markdown="1">
1119 <summary>Show more</summary>
1120
1121 Two helper scripts live in `benchmarks/` to compare hashing options used by prefix caching and related utilities. They are standalone (no server required) and help choose a hash algorithm before enabling prefix caching in production.
1122
1123 - `benchmarks/benchmark_hash.py`: Micro-benchmark that measures per-call latency of three implementations on a representative `(bytes, tuple[int])` payload.
1124
1125 ```bash
1126 python benchmarks/benchmark_hash.py --iterations 20000 --seed 42
1127 ```
1128
1129 - `benchmarks/benchmark_prefix_block_hash.py`: End-to-end block hashing benchmark that runs the full prefix-cache hash pipeline (`hash_block_tokens`) across many fake blocks and reports throughput.
1130
1131 ```bash
1132 python benchmarks/benchmark_prefix_block_hash.py --num-blocks 20000 --block-size 32 --trials 5
1133 ```
1134
1135 Supported algorithms: `sha256`, `sha256_cbor`, `xxhash`, `xxhash_cbor`. Install optional deps to exercise all variants:
1136
1137 ```bash
1138 uv pip install xxhash cbor2
1139 ```
1140
1141 If an algorithm’s dependency is missing, the script will skip it and continue.
1142
1143 </details>
1144
1145 ### ⚡ Request Prioritization Benchmark
1146
1147 <details class="admonition abstract" markdown="1">
1148 <summary>Show more</summary>
1149
1150 Benchmark the performance of request prioritization in vLLM.
1151
1152 #### Basic Prioritization Test
1153
1154 ```bash
1155 python3 benchmarks/benchmark_prioritization.py \
1156 --model meta-llama/Llama-2-7b-chat-hf \
1157 --input-len 128 \
1158 --output-len 64 \
1159 --num-prompts 100 \
1160 --scheduling-policy priority
1161 ```
1162
1163 #### Multiple Sequences per Prompt
1164
1165 ```bash
1166 python3 benchmarks/benchmark_prioritization.py \
1167 --model meta-llama/Llama-2-7b-chat-hf \
1168 --input-len 128 \
1169 --output-len 64 \
1170 --num-prompts 100 \
1171 --scheduling-policy priority \
1172 --n 2
1173 ```
1174
1175 </details>
1176
1177 ### 👁️ Multi-Modal Benchmark
1178
1179 <details class="admonition abstract" markdown="1">
1180 <summary>Show more</summary>
1181
1182 Benchmark the performance of multi-modal requests in vLLM.
1183
1184 #### Images (ShareGPT4V)
1185
1186 Start vLLM:
1187
1188 ```bash
1189 vllm serve Qwen/Qwen2.5-VL-7B-Instruct \
1190 --dtype bfloat16 \
1191 --limit-mm-per-prompt '{"image": 1}' \
1192 --allowed-local-media-path /path/to/sharegpt4v/images
1193 ```
1194
1195 Send requests with images:
1196
1197 ```bash
1198 vllm bench serve \
1199 --backend openai-chat \
1200 --model Qwen/Qwen2.5-VL-7B-Instruct \
1201 --dataset-name sharegpt \
1202 --dataset-path /path/to/ShareGPT4V/sharegpt4v_instruct_gpt4-vision_cap100k.json \
1203 --num-prompts 100 \
1204 --save-result \
1205 --result-dir ~/vllm_benchmark_results \
1206 --save-detailed \
1207 --endpoint /v1/chat/completions
1208 ```
1209
1210 #### Videos (ShareGPT4Video)
1211
1212 Start vLLM:
1213
1214 ```bash
1215 vllm serve Qwen/Qwen2.5-VL-7B-Instruct \
1216 --dtype bfloat16 \
1217 --limit-mm-per-prompt '{"video": 1}' \
1218 --allowed-local-media-path /path/to/sharegpt4video/videos
1219 ```
1220
1221 Send requests with videos:
1222
1223 ```bash
1224 vllm bench serve \
1225 --backend openai-chat \
1226 --model Qwen/Qwen2.5-VL-7B-Instruct \
1227 --dataset-name sharegpt \
1228 --dataset-path /path/to/ShareGPT4Video/llava_v1_5_mix665k_with_video_chatgpt72k_share4video28k.json \
1229 --num-prompts 100 \
1230 --save-result \
1231 --result-dir ~/vllm_benchmark_results \
1232 --save-detailed \
1233 --endpoint /v1/chat/completions
1234 ```
1235
1236 #### Synthetic Random Images (random-mm)
1237
1238 Generate synthetic image inputs alongside random text prompts to stress-test vision models without external datasets.
1239
1240 Notes:
1241
1242 - For online benchmarks, use `--backend openai-chat` with endpoint `/v1/chat/completions`.
1243 - For offline benchmarks, use `--backend vllm-chat` (see [Offline Throughput Benchmark](#-offline-throughput-benchmark) for an example).
1244
1245 Start the server (example):
1246
1247 ```bash
1248 vllm serve Qwen/Qwen2.5-VL-3B-Instruct \
1249 --dtype bfloat16 \
1250 --max-model-len 16384 \
1251 --limit-mm-per-prompt '{"image": 3, "video": 0}' \
1252 --mm-processor-kwargs max_pixels=1003520
1253 ```
1254
1255 Benchmark. It is recommended to use the flag `--ignore-eos` to simulate real responses. You can set the size of the output via the arg `random-output-len`.
1256
1257 Ex.1: Fixed number of items and a single image resolution, enforcing generation of approx 40 tokens:
1258
1259 ```bash
1260 vllm bench serve \
1261 --backend openai-chat \
1262 --model Qwen/Qwen2.5-VL-3B-Instruct \
1263 --endpoint /v1/chat/completions \
1264 --dataset-name random-mm \
1265 --num-prompts 100 \
1266 --max-concurrency 10 \
1267 --random-prefix-len 25 \
1268 --random-input-len 300 \
1269 --random-output-len 40 \
1270 --random-range-ratio 0.2 \
1271 --random-mm-base-items-per-request 2 \
1272 --random-mm-limit-mm-per-prompt '{"image": 3, "video": 0}' \
1273 --random-mm-bucket-config '{(224, 224, 1): 1.0}' \
1274 --request-rate inf \
1275 --ignore-eos \
1276 --seed 42
1277 ```
1278
1279 The number of items per request can be controlled by passing multiple image buckets:
1280
1281 ```bash
1282 --random-mm-base-items-per-request 2 \
1283 --random-mm-num-mm-items-range-ratio 0.5 \
1284 --random-mm-limit-mm-per-prompt '{"image": 4, "video": 0}' \
1285 --random-mm-bucket-config '{(256, 256, 1): 0.7, (720, 1280, 1): 0.3}' \
1286 ```
1287
1288 Flags specific to `random-mm`:
1289
1290 - `--random-mm-base-items-per-request`: base number of multimodal items per request.
1291 - `--random-mm-num-mm-items-range-ratio`: vary item count uniformly in the closed integer range [floor(n·(1−r)), ceil(n·(1+r))]. Set r=0 to keep it fixed; r=1 allows 0 items.
1292 - `--random-mm-limit-mm-per-prompt`: per-modality hard caps, e.g. '{"image": 3, "video": 0}'.
1293 - `--random-mm-bucket-config`: dict mapping (H, W, T) → probability. Entries with probability 0 are removed; remaining probabilities are renormalized to sum to 1. Use T=1 for images. Set any T>1 for videos (video sampling not yet supported).
1294
1295 Behavioral notes:
1296
1297 - If the requested base item count cannot be satisfied under the provided per-prompt limits, the tool raises an error rather than silently clamping.
1298
1299 How sampling works:
1300
1301 - Determine per-request item count k by sampling uniformly from the integer range defined by `--random-mm-base-items-per-request` and `--random-mm-num-mm-items-range-ratio`, then clamp k to at most the sum of per-modality limits.
1302 - For each of the k items, sample a bucket (H, W, T) according to the normalized probabilities in `--random-mm-bucket-config`, while tracking how many items of each modality have been added.
1303 - If a modality (e.g., image) reaches its limit from `--random-mm-limit-mm-per-prompt`, all buckets of that modality are excluded and the remaining bucket probabilities are renormalized before continuing.
1304 This should be seen as an edge case, and if this behavior can be avoided by setting `--random-mm-limit-mm-per-prompt` to a large number. Note that this might result in errors due to engine config `--limit-mm-per-prompt`.
1305 - The resulting request contains synthetic image data in `multi_modal_data` (OpenAI Chat format). When `random-mm` is used with the OpenAI Chat backend, prompts remain text and MM content is attached via `multi_modal_data`.
1306
1307 </details>
1308
1309 ### 🔬 Multimodal Processor Benchmark
1310
1311 Benchmark per-stage latency of the multimodal (MM) input processor pipeline, including the encoder forward pass. This is useful for profiling preprocessing bottlenecks in vision-language models.
1312
1313 <details class="admonition abstract" markdown="1">
1314 <summary>Show more</summary>
1315
1316 The benchmark measures the following stages for each request:
1317
1318 | Stage | Description |
1319 | ----- | ----------- |
1320 | `get_mm_hashes_secs` | Time spent hashing multimodal inputs |
1321 | `get_cache_missing_items_secs` | Time spent looking up the processor cache |
1322 | `apply_hf_processor_secs` | Time spent in the HuggingFace processor |
1323 | `merge_mm_kwargs_secs` | Time spent merging multimodal kwargs |
1324 | `apply_prompt_updates_secs` | Time spent updating prompt tokens |
1325 | `preprocessor_total_secs` | Total preprocessing time |
1326 | `encoder_forward_secs` | Time spent in the encoder model forward pass |
1327 | `num_encoder_calls` | Number of encoder invocations per request |
1328
1329 The benchmark also reports end-to-end latency (TTFT + decode time) per
1330 request. Use `--metric-percentiles` to select which percentiles to report
1331 (default: p99) and `--output-json` to save results.
1332
1333 #### Basic Example with Synthetic Data (random-mm)
1334
1335 ```bash
1336 vllm bench mm-processor \
1337 --model Qwen/Qwen2-VL-7B-Instruct \
1338 --dataset-name random-mm \
1339 --num-prompts 50 \
1340 --random-input-len 300 \
1341 --random-output-len 40 \
1342 --random-mm-base-items-per-request 2 \
1343 --random-mm-limit-mm-per-prompt '{"image": 3, "video": 0}' \
1344 --random-mm-bucket-config '{(256, 256, 1): 0.7, (720, 1280, 1): 0.3}'
1345 ```
1346
1347 #### Using a HuggingFace Dataset
1348
1349 ```bash
1350 vllm bench mm-processor \
1351 --model Qwen/Qwen2-VL-7B-Instruct \
1352 --dataset-name hf \
1353 --dataset-path lmarena-ai/VisionArena-Chat \
1354 --hf-split train \
1355 --num-prompts 100
1356 ```
1357
1358 #### Warmup, Custom Percentiles, and JSON Output
1359
1360 ```bash
1361 vllm bench mm-processor \
1362 --model Qwen/Qwen2-VL-7B-Instruct \
1363 --dataset-name random-mm \
1364 --num-prompts 200 \
1365 --num-warmups 5 \
1366 --random-input-len 300 \
1367 --random-output-len 40 \
1368 --random-mm-base-items-per-request 1 \
1369 --metric-percentiles 50,90,95,99 \
1370 --output-json results.json
1371 ```
1372
1373 See [`vllm bench mm-processor`](../cli/bench/mm_processor.md) for the full argument reference.
1374
1375 </details>
1376
1377 ### Embedding Benchmark
1378
1379 Benchmark the performance of embedding requests in vLLM.
1380
1381 <details class="admonition abstract" markdown="1">
1382 <summary>Show more</summary>
1383
1384 #### Text Embeddings
1385
1386 Unlike generative models which use Completions API or Chat Completions API,
1387 you should set `--backend openai-embeddings` and `--endpoint /v1/embeddings` to use the Embeddings API.
1388
1389 You can use any text dataset to benchmark the model, such as ShareGPT.
1390
1391 Start the server:
1392
1393 ```bash
1394 vllm serve jinaai/jina-embeddings-v3 --trust-remote-code
1395 ```
1396
1397 Run the benchmark:
1398
1399 ```bash
1400 # download dataset
1401 # wget https://huggingface.co/datasets/anon8231489123/ShareGPT_Vicuna_unfiltered/resolve/main/ShareGPT_V3_unfiltered_cleaned_split.json
1402 vllm bench serve \
1403 --model jinaai/jina-embeddings-v3 \
1404 --backend openai-embeddings \
1405 --endpoint /v1/embeddings \
1406 --dataset-name sharegpt \
1407 --dataset-path <your data path>/ShareGPT_V3_unfiltered_cleaned_split.json
1408 ```
1409
1410 #### Multi-modal Embeddings
1411
1412 Unlike generative models which use Completions API or Chat Completions API,
1413 you should set `--endpoint /v1/embeddings` to use the Embeddings API. The backend to use depends on the model:
1414
1415 - CLIP: `--backend openai-embeddings-clip`
1416 - VLM2Vec: `--backend openai-embeddings-vlm2vec`
1417
1418 For other models, please add your own implementation inside [vllm/benchmarks/lib/endpoint_request_func.py](../../vllm/benchmarks/lib/endpoint_request_func.py) to match the expected instruction format.
1419
1420 You can use any text or multi-modal dataset to benchmark the model, as long as the model supports it.
1421 For example, you can use ShareGPT and VisionArena to benchmark vision-language embeddings.
1422
1423 Serve and benchmark CLIP:
1424
1425 ```bash
1426 # Run this in another process
1427 vllm serve openai/clip-vit-base-patch32
1428
1429 # Run these one by one after the server is up
1430 # download dataset
1431 # wget https://huggingface.co/datasets/anon8231489123/ShareGPT_Vicuna_unfiltered/resolve/main/ShareGPT_V3_unfiltered_cleaned_split.json
1432 vllm bench serve \
1433 --model openai/clip-vit-base-patch32 \
1434 --backend openai-embeddings-clip \
1435 --endpoint /v1/embeddings \
1436 --dataset-name sharegpt \
1437 --dataset-path <your data path>/ShareGPT_V3_unfiltered_cleaned_split.json
1438
1439 vllm bench serve \
1440 --model openai/clip-vit-base-patch32 \
1441 --backend openai-embeddings-clip \
1442 --endpoint /v1/embeddings \
1443 --dataset-name hf \
1444 --dataset-path lmarena-ai/VisionArena-Chat
1445 ```
1446
1447 Serve and benchmark VLM2Vec:
1448
1449 ```bash
1450 # Run this in another process
1451 vllm serve TIGER-Lab/VLM2Vec-Full --runner pooling \
1452 --trust-remote-code \
1453 --chat-template examples/pooling/embed/template/vlm2vec_phi3v.jinja
1454
1455 # Run these one by one after the server is up
1456 # download dataset
1457 # wget https://huggingface.co/datasets/anon8231489123/ShareGPT_Vicuna_unfiltered/resolve/main/ShareGPT_V3_unfiltered_cleaned_split.json
1458 vllm bench serve \
1459 --model TIGER-Lab/VLM2Vec-Full \
1460 --backend openai-embeddings-vlm2vec \
1461 --endpoint /v1/embeddings \
1462 --dataset-name sharegpt \
1463 --dataset-path <your data path>/ShareGPT_V3_unfiltered_cleaned_split.json
1464
1465 vllm bench serve \
1466 --model TIGER-Lab/VLM2Vec-Full \
1467 --backend openai-embeddings-vlm2vec \
1468 --endpoint /v1/embeddings \
1469 --dataset-name hf \
1470 --dataset-path lmarena-ai/VisionArena-Chat
1471 ```
1472
1473 </details>
1474
1475 ### Reranker Benchmark
1476
1477 Benchmark the performance of rerank requests in vLLM.
1478
1479 <details class="admonition abstract" markdown="1">
1480 <summary>Show more</summary>
1481
1482 Unlike generative models which use Completions API or Chat Completions API,
1483 you should set `--backend vllm-rerank` and `--endpoint /v1/rerank` to use the Reranker API.
1484
1485 For reranking, the only supported dataset is `--dataset-name random-rerank`
1486
1487 Start the server:
1488
1489 ```bash
1490 vllm serve BAAI/bge-reranker-v2-m3
1491 ```
1492
1493 Run the benchmark:
1494
1495 ```bash
1496 vllm bench serve \
1497 --model BAAI/bge-reranker-v2-m3 \
1498 --backend vllm-rerank \
1499 --endpoint /v1/rerank \
1500 --dataset-name random-rerank \
1501 --tokenizer BAAI/bge-reranker-v2-m3 \
1502 --random-input-len 512 \
1503 --num-prompts 10 \
1504 --random-batch-size 5
1505 ```
1506
1507 For reranker models, this will create `num_prompts / random_batch_size` requests with
1508 `random_batch_size` "documents" where each one has close to `random_input_len` tokens.
1509 In the example above, this results in 2 rerank requests with 5 "documents" each where
1510 each document has close to 512 tokens.
1511
1512 Please note that the `/v1/rerank` is also supported by embedding models. So if you're running
1513 with an embedding model, also set `--no_reranker`. Because in this case the query is
1514 treated as an individual prompt by the server, here we send `random_batch_size - 1` documents
1515 to account for the extra prompt which is the query. The token accounting to report the
1516 throughput numbers correctly is also adjusted.
1517
1518 </details>