Changelog¶
All notable changes to this project are documented here. The format follows Keep a Changelog, and versions follow SemVer (pre-1.0: minor versions may include breaking changes).
[0.1.0] - 2026-09-20¶
First PyPI release.
Added¶
- Installable package
benchrig(importbenchrig) with abenchrigconsole script (alsopython -m benchrig). benchrig --version,--configand--scenarios-dir. The defaultconfig.yamland all scenario suites are bundled;./config.yaml,./scenariosor$BENCHRIG_CONFIGoverride them.- Direct ONNX models are looked up in
$BENCHRIG_MODEL_DIRS, then./models, then~/.benchrig/models. - Benchmarking across Ollama, Microsoft Foundry Local and direct ONNX Runtime GenAI (CUDA), with hardware telemetry, sandboxed coding tests, reasoning/speed/context/Polish suites and 1:1 cross-engine comparison reports.
-
CI (Python 3.10-3.13, wheel smoke test) and a trusted-publishing workflow for TestPyPI and PyPI.
-
Prism runtime (
--runtime prism,prism:prefix,prism:config section): benchmark a Prism server (prism serve) next to Ollama, Foundry Local and direct ONNX. SupportsPRISM_API_KEY,--check,--pull-recommended(viaprism pull), 1:1 pairs with aprism:model, and records the device Prism reports.--models installedskips Prism'sollama:proxies. Reports label the runtime as "Prism" and the cross-engine table covers every non-Ollama runtime. - Documentation site (MkDocs Material, deployed to GitHub Pages) with a new Runtimes page; docs files were
renamed to lowercase names (
docs/cli.md,docs/configuration.md, ...).
Changed (measurement methodology; results from earlier versions are not comparable)¶
- Context suite: on Ollama each step is preceded by an untimed request with the same
num_ctx, so the timed request no longer includes model reload (it was about 4 to 7 s per step and dominated TTFT). Prompts are sized from the window (fill_ratio, default 0.75) instead of a fixed multiplier, the real prompt size is recorded (prompt_tokens_actual), and a 1024 step is added. - Prefill: reports use one definition for every runtime (
prefill_eff_tok_per_sec, prompt tokens / time to first token). The engine-reported value stays asprompt_tok_per_sec, andprefill_sourcesays where it came from. - VRAM: GPU memory is read before each model is loaded; scorecards add
vram_baseline_mbandvram_model_mb(peak minus baseline).peak_vram_mbremains the whole-GPU peak. -
Thinking models:
benchmark.thinking_models/thinking_token_multiplierraisenum_predictfor models such asdeepseek-r1on the coding, reasoning and polish suites. Results and reports flag responses that stopped at the token limit (truncated,truncated_runs,finish_reason). -
Repetitions (
--runs N): repetitions after the first send their prompts with a short marker, because Ollama caches the prompt prefix and a repeated prompt measured 0.006 s of prefill instead of 0.12 s. Each repetition uses its own seed (execution_alignment_1to1.seed+ N), andexecution_alignment_1to1(temperature,top_p,seed,context_tokens) is now actually applied as default sampling on every runtime (it was documented but unused); its unused keys were removed. Scorecards report the min-max of the headline metrics over repetitions (runs,spread). - Reasoning suite: six new scenarios (two trains, knights and knaves, distinct-digit numbers, a recurrence, chained percentages,
letter counting), nine in total, with a new
final_answercheck type (the lastFinal answer:line must match in full). Their expected answers are recomputed by independent solvers intests/test_scenarios.py. - Ollama
think: thethinkingstream is read.ttft_secis now the first token of any kind (latency), withanswer_ttft_sec,think_time_secandthinking_charsalongside; a response that never left the thinking phase no longer reports 0.0 s.benchmark.thinksets Ollama'sthinkper suite (speed and context off by default) and is sent only to models Ollama lists as able to think.thinking_token_multiplierdefault 6 -> 12; it also applies withthink: false(deepseek-r1:14b without thinking still reached the base budget). - Context suite: each step hides a fact in the text and asks for it, so it scores whether the model uses the context
(
retrieved,context_retrieval_pct); wrong answers show as FAIL/"missed the fact" instead of ERROR, and failed requests keep theirerror. - After the context suite an untimed request puts the model back at the default context size. It used to leave Ollama at
num_ctx8192, so with--runs Nthe first request of the next repetition paid a model reload (TTFT about 0.8 s instead of 0.06 s). - Prism token counts: results say when the counts are estimates (
usage_estimated, with a note in the reports) instead of silently guessing; Prism now sends exactusageand telemetry in streamed responses (stream_options.include_usage). - Model memory of a runtime that cannot unload: when a model is still loaded at baseline time (Prism), the model-only figure is
-(vram_baseline_dirty) instead of a value that understates the model. - The 1:1 report also lists the min-max spread of repeated runs, and three easier reasoning scenarios (bat and ball, multiples of three or five, letters in one word) bring the suite to twelve.
- Decode speed is weighted by tokens (total tokens / total generation time); the plain mean is kept as
avg_eval_tok_sec_mean. - New figures:
cold_start_sec(first request),gpu_fit_pct(Ollama/api/ps, share of the model in GPU memory) andtokens_per_joule(GPU power), shown in a "Start-up, GPU fit & efficiency" table.
Fixed¶
exact_or_containsmatches numbers as whole numbers:11/60,21/60and1/60were accepted for1/6, and1114.60for114.6.- Reasoning:
regexanswers are matched against the normalized end of the answer (markdown, bullets and line breaks collapsed), so a multi-line or bulletedBox 1: ... Box 2: ...conclusion is accepted (it was rejected because.did not match newlines), while the bundled patterns use bounded gaps and cannot be satisfied by words scattered through the reasoning (an unbounded multi-line match accepted wrong answers). LaTeX answers such as\boxed{\dfrac{1}{6}}now match1/6. A response cut off inside<think>is no longer scored on its reasoning trace (it produced false passes). Results recordanswer_excerptandtruncated_thinking. - 1:1 comparison report: it compares the Ollama scorecard that matches the other model (by name and size tag) instead of the first one in the list, and it only uses that model's own records (it used to include every Ollama model's results, so another model's errors showed up in the scenario breakdown). Speed, context, reasoning and polish scenarios show OK/PASS/FAIL from their own fields instead of "FAIL (0/0)", cut-off answers are marked, and a Prism run is labelled "Prism", not "MS Foundry", in the title and in every "who is faster" cell.
- Coding: code inside
<think>traces is ignored, and a response cut off before its code is complete is reported as truncated instead ofname '...' is not defined. FoundryClientreports the engine that actually serves each model (fromowned_by, or theollama:prefix) instead of always "ONNX Runtime GenAI"; matters for multi-engine servers such as Prism.- With an explicit endpoint (
auto_detect_port: false)load_model/unload_modelno longer call thefoundryCLI (which talks to a different daemon);load_modelreports whether the server lists the model.
Changed¶
- The agent skills and MCP servers moved to local-coders.
core/andreporting/moved tobenchrig.coreandbenchrig.reporting;benchmark.pyis nowbenchrig.cli(runbenchrig ...instead ofpython3 benchmark.py ...).- The CUDA library bootstrap looks in the active environment's
site-packagesinstead of a.venvnext to the script. requirements*.txtreplaced bypip install -e ".[dev]".