fix(bench): drop the stale calibration caption and read compression from JSON (#525)

Two accuracy defects in reader-facing benchmark output.

The persist charts' caption still said "Save: full index → .tv file,
calibration frozen". #474 removed automatic TQ+ calibration, so a default
index performs none during `save()` and there is nothing to freeze. The
claim shipped in four figures — `docs/{arm,x86}_persist_{st,mt}.svg` —
which are regenerated here. The insert captions lost the same claim
earlier; this was the last one.

`write_compression_chart` hardcoded its three rows while every other
chart in the file reads `results/`. The numbers happened to agree with
`compression.json`, but only by hand: a rerun that moved the JSON would
leave the shipped figure silently stale, which is the defect rather than
the current values. It now reads the JSON, and asserts the 2-bit and
4-bit rows of each dataset agree on `fp32_mb` — they describe the same
corpus, so a disagreement means one is stale.

Verified both directions: with the current data `compression.svg`
regenerates byte-identical, and perturbing a value in the JSON moves the
chart, so the coupling is real rather than decorative.

Closes #492

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ryan Codrai
2026-08-10 19:44:08 +01:00
committed by GitHub
parent 4d2c82d5b4
commit 44ae40b93e
5 changed files with 27 additions and 10 deletions
+23 -6
View File
@@ -467,7 +467,7 @@ def write_persist_panel(arch, hw_label, thread_key, thread_label, filename):
{style_block()}
<rect width="100%" height="100%" fill="#ffffff" />
<text x="{margin["left"]}" y="32" class="title">Save / Load — {xe(hw_label)}{xe(thread_label)}</text>
<text x="{margin["left"]}" y="52" class="subtitle">100K vectors. Save: full index → .tv file, calibration frozen. Load → first search: open a cold .tv and run the first query. Round-trip: mutate → save → load → search. Median of 5 runs.</text>
<text x="{margin["left"]}" y="52" class="subtitle">100K vectors. Save: full index → .tv file. Load → first search: open a cold .tv and run the first query. Round-trip: mutate → save → load → search. Median of 5 runs.</text>
{body}
</svg>
"""
@@ -576,11 +576,28 @@ def write_recall_panel(dim_key, dim_label, filename, y_lo=0.85):
def write_compression_chart(filename):
datasets = [
("GloVe|d=200", 76.3, 9.9, 5.1),
("OpenAI|d=1536", 585.9, 73.6, 37.0),
("OpenAI|d=3072", 1171.9, 146.9, 73.6),
]
# Read from results/compression.json rather than restating it. The
# hardcoded copy happened to agree, but only by hand — a rerun that
# moved the JSON left the shipped figure silently stale (#492).
raw = load_json("compression.json")
def cell(key):
d = raw[key]
return d["fp32_mb"], d["index_mb"]
datasets = []
for label, stem in (
("GloVe|d=200", "glove_d200"),
("OpenAI|d=1536", "openai_d1536"),
("OpenAI|d=3072", "openai_d3072"),
):
fp32, four_bit = cell(f"{stem}_4bit")
fp32_two, two_bit = cell(f"{stem}_2bit")
assert fp32 == fp32_two, (
f"{stem}: the 2-bit and 4-bit rows disagree on fp32_mb "
f"({fp32_two} vs {fp32}) — one of them is stale"
)
datasets.append((label, fp32, four_bit, two_bit))
width, height = 900, 460
margin = {"top": 82, "right": 32, "bottom": 108, "left": 84}
pw = width - margin["left"] - margin["right"]
+1 -1
View File
@@ -14,7 +14,7 @@
</style>
<rect width="100%" height="100%" fill="#ffffff" />
<text x="70" y="32" class="title">Save / Load — ARM (GCP c4a-standard-8, Google Axion, 8 vCPUs) — Multi-threaded</text>
<text x="70" y="52" class="subtitle">100K vectors. Save: full index → .tv file, calibration frozen. Load → first search: open a cold .tv and run the first query. Round-trip: mutate → save → load → search. Median of 5 runs.</text>
<text x="70" y="52" class="subtitle">100K vectors. Save: full index → .tv file. Load → first search: open a cold .tv and run the first query. Round-trip: mutate → save → load → search. Median of 5 runs.</text>
<line x1="70.0" y1="384.0" x2="481.3333333333333" y2="384.0" stroke="#e5e7eb" stroke-width="1" />
<text x="60.0" y="388.0" text-anchor="end" class="tick">0.0</text>
<line x1="70.0" y1="325.6" x2="481.3333333333333" y2="325.6" stroke="#e5e7eb" stroke-width="1" />

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

+1 -1
View File
@@ -14,7 +14,7 @@
</style>
<rect width="100%" height="100%" fill="#ffffff" />
<text x="70" y="32" class="title">Save / Load — ARM (GCP c4a-standard-8, Google Axion, 8 vCPUs) — Single-threaded</text>
<text x="70" y="52" class="subtitle">100K vectors. Save: full index → .tv file, calibration frozen. Load → first search: open a cold .tv and run the first query. Round-trip: mutate → save → load → search. Median of 5 runs.</text>
<text x="70" y="52" class="subtitle">100K vectors. Save: full index → .tv file. Load → first search: open a cold .tv and run the first query. Round-trip: mutate → save → load → search. Median of 5 runs.</text>
<line x1="70.0" y1="384.0" x2="481.3333333333333" y2="384.0" stroke="#e5e7eb" stroke-width="1" />
<text x="60.0" y="388.0" text-anchor="end" class="tick">0.0</text>
<line x1="70.0" y1="325.6" x2="481.3333333333333" y2="325.6" stroke="#e5e7eb" stroke-width="1" />

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

+1 -1
View File
@@ -14,7 +14,7 @@
</style>
<rect width="100%" height="100%" fill="#ffffff" />
<text x="70" y="32" class="title">Save / Load — x86 (Intel Sapphire Rapids, 8 vCPUs) — Multi-threaded</text>
<text x="70" y="52" class="subtitle">100K vectors. Save: full index → .tv file, calibration frozen. Load → first search: open a cold .tv and run the first query. Round-trip: mutate → save → load → search. Median of 5 runs.</text>
<text x="70" y="52" class="subtitle">100K vectors. Save: full index → .tv file. Load → first search: open a cold .tv and run the first query. Round-trip: mutate → save → load → search. Median of 5 runs.</text>
<line x1="70.0" y1="384.0" x2="481.3333333333333" y2="384.0" stroke="#e5e7eb" stroke-width="1" />
<text x="60.0" y="388.0" text-anchor="end" class="tick">0.0</text>
<line x1="70.0" y1="325.6" x2="481.3333333333333" y2="325.6" stroke="#e5e7eb" stroke-width="1" />

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

+1 -1
View File
@@ -14,7 +14,7 @@
</style>
<rect width="100%" height="100%" fill="#ffffff" />
<text x="70" y="32" class="title">Save / Load — x86 (Intel Sapphire Rapids, 8 vCPUs) — Single-threaded</text>
<text x="70" y="52" class="subtitle">100K vectors. Save: full index → .tv file, calibration frozen. Load → first search: open a cold .tv and run the first query. Round-trip: mutate → save → load → search. Median of 5 runs.</text>
<text x="70" y="52" class="subtitle">100K vectors. Save: full index → .tv file. Load → first search: open a cold .tv and run the first query. Round-trip: mutate → save → load → search. Median of 5 runs.</text>
<line x1="70.0" y1="384.0" x2="481.3333333333333" y2="384.0" stroke="#e5e7eb" stroke-width="1" />
<text x="60.0" y="388.0" text-anchor="end" class="tick">0.0</text>
<line x1="70.0" y1="325.6" x2="481.3333333333333" y2="325.6" stroke="#e5e7eb" stroke-width="1" />

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB