BatchBench
Load generation for OpenAI-compatible chat endpoints. A Rust core with a thin Python wrapper, published as prebuilt wheels:
uv pip install batchbench
Three entrypoints:
| Command | What it does |
|---|---|
batchbench |
Independent requests at a fixed concurrency with controlled token shapes |
batchbench-agent |
Stateful multi-turn sessions, sampled or replayed from a manifest |
batchbench-export-plans |
Builds a replay manifest from prompt-chain records in ClickHouse |
Independent requests
batchbench \
--model gpt-4o-mini \
--users 8 \
--requests-per-user 2 \
--input-tokens 256 \
--output-tokens 64 \
--output-vary 0
Output length is enforced with min_tokens/max_tokens; pass --sglang for
backends that use min_new_tokens/max_new_tokens. Ctrl+C cancels active
requests and prints a partial summary. The same run is available from Python:
import batchbench
report = batchbench.run_benchmark({
"endpoint": "https://example.com/v1/chat/completions",
"user_count": 1,
"mode": batchbench.finite_mode(requests_per_user=1),
"request_body": batchbench.request_entry(
{"model": "gpt-4o-mini", "messages": [{"role": "user", "content": "ping"}]},
line_idx=0, input_tokens=1),
"requests": [batchbench.request_entry(
{"model": "gpt-4o-mini", "messages": [{"role": "user", "content": "ping"}], "max_tokens": 4},
line_idx=0, input_tokens=1)],
"dry_run": True,
})
Multi-turn sessions
batchbench-agent runs concurrent agent loops. Within a loop, each request appends
the model's reply and a synthetic tool result to the conversation and sends it again,
so every turn reuses the previous prompt as a prefix. Token shapes are fixed or
log-normal:
batchbench-agent \
--model Qwen/Qwen3-8B \
--host http://localhost:8000 \
--agents 16 \
--input-tokens 256 \
--output-tokens 64 \
--environment-tokens 128 \
--tool-invocations 8 \
--tool-call-latency-ms 250
Each --*-tokens flag has a --*-lognorm-median / --*-lognorm-sigma /
--*-lognorm-max family; --seed makes sampling reproducible. --tokenizer-model
names the tokenizer when the endpoint's model name is not a Hugging Face identifier
(a model id, a tokenizer.json, or a directory containing one). Every request carries a
per-agent user field and routing header so a gateway can keep a session on one
worker; --user-prefix, --disable-user-tagging, and
--dp-rank-perfect-routing control that.
Replaying a manifest
A manifest is a JSONL file with one trajectory per line: its requests, their prompt and output token counts, the gaps between them, and optionally the prompt's content blocks. The agent binary replays it instead of sampling:
batchbench-agent \
--model Qwen/Qwen3-8B \
--host http://localhost:8000 \
--agent-plans-jsonl plans.jsonl \
--admission open-loop \
--time-scale 2 \
--agent-events-jsonl events.jsonl \
--results-csv results.csv
--admission open-loop starts each trajectory at its recorded offset; the default
closed-loop admission fills --max-active-agents slots in file order. --time-scale N
replays a recorded hour in 1/N hours. Block text is generated from each block's seed
at exactly the requested token count, so blocks with equal seeds send identical bytes
and shared prefixes exercise prefix caching. --dry-run checks a manifest without
sending requests. The format is specified in docs/manifest.md;
examples/trajectory-replay/ has one file per schema version.
Building a manifest from records
batchbench-export-plans reads a window of prompt-chain records from ClickHouse,
rebuilds sessions from the chains, and writes a schema version 2 manifest:
uv pip install "batchbench[export]"
CLICKHOUSE_URL=https://warehouse.example.com:8443 CLICKHOUSE_USER=... CLICKHOUSE_PASSWORD=... \
batchbench-export-plans \
--chains-table chains_current --analytics-table requests \
--start 2026-09-01T09:00:00Z --end 2026-09-01T10:00:00Z \
--model vendor/model-a \
--sample 0.1 --seed 7 --stratify-by-session-length \
--output plans.jsonl
The input tables it expects, and how sessions are reconstructed, are described in docs/export-plans.md.
Report
Each run prints total prompt and completion tokens from the responses' usage and
request latency p50/p90/p99. Agent runs add the estimated cached prompt tokens under
perfect prefix caching and the end-to-end session latency. --results-csv persists
the same figures; --agent-events-jsonl records per-trajectory admission and
completion times.
batchbench-harness drives runs on remote GPU hosts; see HARNESS.md.
Building from source
cargo build --release --manifest-path rust/Cargo.toml --bin batchbench
cargo build --release --manifest-path rust/Cargo.toml --bin batchbench-agent
Releases are cut by Release Please; a v* tag builds platform wheels and publishes
them to PyPI.
Metadata
Release files for batchbench 0.7.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| batchbench-0.7.0-cp39-abi3-win_amd64.whl | CPython 3.9 | abi3 | Windows x86-64 | Details |
| batchbench-0.7.0-cp39-abi3-manylinux_2_28_x86_64.whl | CPython 3.9 | abi3 | Linux glibc 2.28+ x86-64 | Details |
| batchbench-0.7.0-cp39-abi3-macosx_11_0_arm64.whl | CPython 3.9 | abi3 | macOS 11.0+ ARM64 | Details |
Total release size: 14.8 MB
Release files / batchbench-0.7.0-cp39-abi3-win_amd64.whl
| Download URL | batchbench-0.7.0-cp39-abi3-win_amd64.whl |
|---|---|
| Size | 4.6 MB |
| Tags | CPython 3.9 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
e03ee58d39cb7ff15c696e908ccf59b8a4c86910d4639a71ea8c081be3d2507a
|
|
BLAKE2b-256 checksum How to use checksums |
c6543ef99fb01ec037f9ddf8f9ebd7c3a2f87783bae7a57daea2d7990e43aef5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.
Transparency logRelease files / batchbench-0.7.0-cp39-abi3-manylinux_2_28_x86_64.whl
| Download URL | batchbench-0.7.0-cp39-abi3-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 5.4 MB |
| Tags | CPython 3.9 Linux glibc 2.28+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
55730eb006d2dcfe19db356c6d9f2113fd8f33670ea8776ebde53724fd09446d
|
|
BLAKE2b-256 checksum How to use checksums |
8aec9d2bb776f9e04bc6f90abba5c4b6d95bcfb56d0a1f65583a5adab6d6b3dc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.
Transparency logRelease files / batchbench-0.7.0-cp39-abi3-macosx_11_0_arm64.whl
| Download URL | batchbench-0.7.0-cp39-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 4.8 MB |
| Tags | CPython 3.9 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
dc804790a98f319e528c80d167887904aa55800306083fcd3b4a35d808d7c8da
|
|
BLAKE2b-256 checksum How to use checksums |
61ac9c495eb9579af92a401c12023527aa9ac75b4bc105037e9bb3f7e61b7dce
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.
Transparency log