Files
2026-07-13 12:24:33 +08:00

158 lines
5.3 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# OpenAI ChatCompletion TTFT Benchmark
Measure **timetofirsttoken (TTFT)** — and optional cachehit latency — from **any
server that speaks the OpenAI `/v1` API** (vLLM, llama.cpp with `--api`,
OpenAIproxy, etc.).
> **Why run it?**
> • Compare *cold* latency vs. *cachehit* latency.
> • Verify whether a KVcache (VRAM, SSD, LMCache, …) actually helps.
> • Collect JSONL you can plot
---
## 1 · Prerequisites
| Requirement | Notes |
|-------------|-------|
| **Running endpoint** | Must expose the OpenAI REST interface (default URL `http://localhost:8000/v1`). |
For more information on how to serve an endpoint using vllm and LMCache,
---
## 2 · Commandline flags
| Flag / shorthand | Default | Meaning |
|------------------|---------|---------|
| `--api_base` | `http://localhost:8000/v1` | URL of the OpenAIstyle endpoint. |
| `--api_key` | `EMPTY` | Any string (ignored by most local servers). |
| `--model` | *first model from* `/models` | Explicit model ID. |
| `-C`, `--context_file` | *see table below* | Document inserted before the prompt. |
| `--max_ctx_tokens` | **131072** | Upper bound *after* truncation. |
| `--prompt` | `"Summarize this text"` | Prompt appended after the document. |
| `--num_following`| **1** | Extra TTFTmeasured requests after the baseline. |
| `-F`, `--flush_cache` | off | Flush GPU KVcache **once** after run1. |
| `--out` | `benchmark.jsonl` | JSONL log (cleared at start). |
### Behaviour of `--context_file`
| Invocation | Document used |
|------------|---------------|
| *(flag omitted)* | Synthetic ASCII filler based on max ctx length input|
| `--context_file` *(no path)* | Bundled `ffmpeg.txt` (one dir up) |
| `--context_file /path/doc.txt` | Exact file you specify |
> **Legacy shorthand**  you may also run
> `python openai_chat_completion_client.py <PORT>`
> and every other option remains default.
---
## 3 · Quick start
Cold + warm measurement (two requests total):
```bash
python openai_chat_completion_client.py --num_following 1
```
Example console output
```
=== Run 1: baseline TTFT ===
TTFT_1 = 0.429s
(no KVcache flush requested)
=== Run 2: TTFT continued ===
TTFT_2 = 0.081s
```
`benchmark.jsonl`
```json
{"run_index":1,"context_tokens":120938,"ttft_seconds":0.429}
{"run_index":2,"context_tokens":120938,"ttft_seconds":0.081}
```
---
## 4 · Advanced use
### 4.1 · Benchmark after cache eviction
```bash
python openai_chat_completion_client.py \
-C war_and_peace.txt \
--num_following 3 \
--flush_cache \
--prompt "Give me a concise outline." \
--out warpeace_flush.jsonl
```
* Run cold
* Cache flushed
* Run cold again (miss)
* Runs3 warm (hits)
### 4.2 · Stress maximum context
```bash
python openai_chat_completion_client.py \
--max_ctx_tokens 131072 \
--num_following 1 -F
```
Generates a kchar filler, truncates to fit
`≤ max_ctx ` tokens (keeps a **2048token safety margin**), then
measures cold vs. warm TTFT.
---
## 5 · Output schema
Each JSONL line contains:
| Key | Type | Description |
|-----|------|-------------|
| `run_index` | int | 1 = baseline, 2… = followups |
| `context_tokens` | int | Tokens after truncation |
| `ttft_seconds` | float | Wallclock seconds to **first** streamed token |
Concatenate multiple logs with `cat` and plot as you like.
---
## 6 · Implementation notes
* **Safety margin**  `SAFETY_MARGIN = 2048` tokens so the request never
overruns model context even on tokenizer quirks.
* **Spinner**  Red arrows animate while waiting for token#1, stop instantly
on arrival for visual TTFT confirmation.
* **Tokenizer fallback**  If the matching tokenizer cant load, the script
degrades to the heuristic “≈ 4 chars=1 token”.
* **Cacheflush routine**  Sends ten *1token* completions built on a
100kchar filler doc to evict KV blocks from VRAM.
## 7 · Batch driver script (`bench_ttft_sweep.sh`)
This is an example basic bash script you might use to do a sweep across different context lengths, combining results to one file for easy comparison of caching methods.
### What the script does
| Step | Detail |
|------|--------|
| **1. Configure variables** | `BENCH` points to the Python benchmark, `MASTER_OUT` is the cumulative log, and `CONTEXT_SIZES` lists the target document lengths (in **tokens**). |
| **2. Persize run** | For each length the script launches the benchmark with:<br>• custom `--max_ctx_tokens` (see above)<br>• one cachehit followup (`--num_following 1`)<br>• an explicit **70B** Llama 3 checkpoint via `--model` |
| **3. Log collation** | Each invocation writes its own JSONL (`ttft_<N>.jsonl`). Those lines are immediately concatenated into **`all_ttft_results.jsonl`**, producing a tidy file like: <br>`{"run_index":1,"context_tokens":32000,"ttft_seconds":0.45}` |
| **4. Done banner** | After the loop finishes you get a green checkmark and the path to the merged log. |
#### Customising
* **Change the model** — edit `--model …` to point at any endpointvisible name.
* **Different sizes** — just tweak the `CONTEXT_SIZES` array.
* **More followups** — bump `--num_following` if you want deeper cachehit sampling.