Skip to content

Corpora of 500 messages, two new routes, five-tab benchmark - #13

Merged
eliahilse merged 2 commits into
mainfrom
corpora
Aug 20, 2026
Merged

Corpora of 500 messages, two new routes, five-tab benchmark#13
eliahilse merged 2 commits into
mainfrom
corpora

Conversation

@eliahilse

Copy link
Copy Markdown
Owner

Reworks the benchmark around what a route actually serves, and puts the three Hyperfly stages on the site.

Why the shape changed. A single large response cannot demonstrate a dictionary — it only contains within-response repetition, which deflate already handles inside the codec. Dictionaries exist for repetition across messages. The old corpora were one response of 500–1000 records, so the profile row was measuring nothing; training on it gave 0–2%, and forcing a win meant putting the payload in the dictionary (7.5 KB of out-of-band data to "save" 2.3 KB on the wire).

Now: 500 independent messages per route, 20–50 records each (or one entity), drawn from a stable universe — a fixed 400-device fleet, a 120-product catalogue, a recurring cast of authors — with Zipf-skewed selection, because real traffic concentrates.

Two new routes: orders (single-entity, ~780 B, where a general compressor has least context) and events (audit log, whose recurring user agents and actor emails are exactly the dictionary case). Protobuf baselines added for both, round-trip verified.

Per message, 500-message corpora

route json gzip br4 proto columnar profiled full dictionary
events 12,687 2,503 2,512 7,190 2,109 896 823 12 KB → 10 req
devices 7,994 1,473 1,422 2,007 896 705 638 5.2 KB → 28 req
feed 6,863 2,307 2,294 4,396 1,908 1,536 1,535 4.9 KB → 14 req
candles 3,225 928 842 2,034 496 496 372 none
orders 782 423 408 388 271 184 188 3.0 KB → 35 req

Against brotli-q4'd JSON — the realistic production baseline — that is 1.5× to 3.1×.

Kept honest rather than tuned away: candles gains nothing from a profile (its only string sits outside the array, so there is no column to key on) and the flat row is left visible; on orders full is larger than profiled, because at 184 bytes Brotli's framing costs more than it saves; and the harness reports the dictionary's own size and break-even, because it is an out-of-band artifact and a reader is entitled to see what it costs.

Site: five tabs, three Hyperfly rows each, footnote stating the training setup and the dictionary cost.

🤖 Generated with Claude Code

eliahilse and others added 2 commits August 20, 2026 16:02
A single large response cannot demonstrate a dictionary: it only contains
within-response repetition, which deflate already handles inside the codec.
Dictionaries exist for repetition ACROSS messages, so the benchmark now models
what a route actually serves — many independent responses over a stable entity
universe, at sizes APIs really return.

- candles, devices and feed become 500-message corpora with 20-50 records per
  message (a chart window, a page of telemetry, a page of posts) instead of one
  1000-row dump, each drawn from a fixed universe of instruments, devices and
  authors with Zipf-skewed selection.
- orders is a new single-entity route (GET /v1/orders/:id, ~780 B of JSON) with
  a fixed 120-product catalogue and 200-customer base. Small responses are the
  case where a general compressor has almost no context to work with.
- events is a new audit-log page (20-50 records) whose recurring user agents,
  actor emails and resource ids are exactly the shape dictionaries exist for.

The harness reports per-message averages plus the dictionary's own size and how
many requests it takes to pay for itself, because a dictionary is an
out-of-band artifact and a reader is entitled to see what it costs:

  route        json   gzip    br4    col   prof   full   dictionary
  candles      3225    928    842    496    496    372   none
  devices      7994   1473   1422    896    705    638   5.2KB, 28 requests
  feed         6863   2307   2294   1908   1536   1535   4.9KB, 14 requests
  events      12687   2503   2512   2109    896    823   12KB, 10 requests
  orders        782    423    408    271    184    188   3.0KB, 35 requests

Two results worth keeping honest about: profiles do nothing for candles, whose
only string sits outside the array and so has no column to key on; and on
orders the brotli pass makes the output slightly larger, because at that size
its framing costs more than it saves.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_hf1
The benchmark now reports bytes per message over 500-message corpora rather
than the size of one large response, because that is the setting in which a
trained dictionary can be measured at all. Each route shows columnar, profiled
and full so the contribution of each stage is visible rather than blended.

Tabs lead with events, where recurring user agents and actor emails make the
profile worth 57%, and end with candles, where it is worth nothing — that
spread is the honest shape of the feature, and the candles row is left in
precisely because it is flat.

The footnote states that the profile is trained on the route's own traffic,
that the dictionary is an out-of-band artifact, and how many requests it takes
to pay for itself. Orders keeps the result where full is larger than profiled:
at 184 bytes Brotli's framing costs more than it saves.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_hf1
@eliahilse
eliahilse merged commit a5a2946 into main Aug 20, 2026
6 checks passed
@eliahilse
eliahilse deleted the corpora branch August 20, 2026 15:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant