Skip to content

feat(hash): rework hash benchmark - fix latency, add bounded-range throughput - #259

Merged
helly25 merged 9 commits into
mainfrom
feat/hash-latency-benchmark-dist
Jul 14, 2026
Merged

feat(hash): rework hash benchmark - fix latency, add bounded-range throughput#259
helly25 merged 9 commits into
mainfrom
feat/hash-latency-benchmark-dist

Conversation

@helly25

@helly25 helly25 commented Jul 14, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes the //mbo/hash:hash_benchmark mixed-length measurement (which produced unreliable, non-reproducible latency numbers) and reframes it. Benchmark-only, by design: the report generator + README rendering land in a follow-up PR after re-measuring on clean main.

Terminology this PR settles on:

  • Latency = cost at an exact length (ns). This is BmHash64 / BmHash128<algo>/<len> — unchanged.
  • Throughput = cost over a realistic, upper-bounded length range (bytes/s). This is the new BmHash64Throughput.

The old bug

BmHash64Latency walked keys by keys[hash & mask] — a functional iteration hash_{n+1} = f(hash_n) that collapses into a short rho-cycle, re-hashing only a few keys and reading as near-zero whenever the cycle hit an empty/tiny key (e.g. fnv1a at 0.27 ns). Removed.

New: throughput over upper-bounded length ranges

  • BmHash64Throughput<algo>/<Short|Web>:<bound> — hashes a realistic [0..L] length mix, truncated and renormalized (kept buckets rescaled to 100%) to each upper bound L, reporting bytes/s → an (upper-bound length -> throughput) curve.
  • Two documented distributions as inverse-CDF tables: Short (log-normal, ≤128 B) and Web (heavy-tailed, ≤4096 B). Ceilings Lmax = 128 B (two L1 cache lines / SSO & AVX-512 transition) and 4096 B (one virtual page).
  • Keys built once per (distribution, bound) with a fixed seed and shared across all algorithms (reproducible, fair; only lengths matter). One anchor key pinned at each bound so the boundary is always represented.
  • Sequential sweep (keys[counter & mask], no hash-indexed walk) → no rho-cycle; the unpredictable length order still defeats the size-dispatch branch predictor, so the branch-misprediction cost is measured (not modelled).
  • String building uses absl::StrCat/absl::StrJoin (adds @abseil-cpp//absl/strings).
  • Exports a throughput_dists context (the full per-distribution inverse-CDF) so every dataset records exactly which mix produced its numbers.

Verification

Both distributions produce smooth, monotonic, anomaly-free, reproducible curves across all algorithms (no 0.27 collapses); bytes/s rises with the bound as larger keys enter the mix.

Follow-up (not this PR)

Re-measure on merged main, then a second PR: report parser/distill for BmHash64Throughput, the latency (exact-length) + throughput (bounded-range) tables/charts, and the README methodology + values.

helly25 added 4 commits July 14, 2026 05:34
BmHash64Latency previously walked keys by keys[hash & mask], a functional
iteration that collapses into a short rho-cycle: it re-hashed only the few keys
on the cycle and read as near-zero whenever the cycle hit an empty/tiny key.

Replace it with two fixed, documented key-length distributions given as
inverse-CDF control points (Short-Identifier, Web-URL). Keys are sampled once
with a fixed seed and SHARED across every algorithm in a run, so the length
multiset is reproducible and identical for all algorithms; a plain sequential
sweep (no hash in the index) then hashes them. Registered as one benchmark per
scenario: BmHash64Latency<algo>/<dist>.

String building uses absl::StrCat/StrJoin (adds @abseil-cpp//absl/strings).

Report generator + README rendering for the new two-scenario latency come in a
follow-up PR after re-measuring on clean main.
to the Short-Identifier distribution. Added {1.0, 4096} to the Web-URL
distribution.Refactored LatencyKeys() generation lambda to loop $K-1$
times and append the explicit ceiling length at the end of each set.
@helly25
helly25 requested a review from Fab-Cat July 14, 2026 08:09
helly25 added 4 commits July 14, 2026 09:13
Two separately-named latency benchmarks each reported as a lone value with no
grouping. Register one family per algo with the scenarios as Args instead
(BmHash64Latency<algo>/0, /1) so it is grouped table data like the throughput
families; emit the Arg-index -> distribution-name legend as the latency_dists
context.
Replace the distribution-aggregate BmHash64Latency with BmHash64Throughput: for
each (distribution, upper bound) it hashes the realistic [0..L] length mix
truncated and renormalized to that bound, reporting bytes/s -- an
(upper-bound -> throughput) curve. Two documented distributions given as
inverse-CDF tables (Short <=128 B, Web <=4096 B); key sets built once with a
fixed seed and shared byte-for-byte across algorithms; one anchor key pinned at
each bound so the boundary is always represented. Sequential sweep (no
hash-indexed walk), so no rho-cycle collapse. The exact-length BmHash64 /
BmHash128 stay as the per-length latency view.
Replace the stale latency_dists Arg-index legend with throughput_dists: the full
inverse-CDF per distribution ("Short=pct:len,...;Web=..."), so a dataset records
exactly which length mix produced its BmHash64Throughput numbers (provenance;
the benchmark names carry only the bound lengths, not the weights).
@helly25 helly25 changed the title feat(hash): rework latency benchmark to fixed key-length distributions feat(hash): rework hash benchmark - fix latency, add bounded-range throughput Jul 14, 2026
@helly25
helly25 enabled auto-merge (squash) July 14, 2026 09:41
@helly25
helly25 merged commit 80a4c8a into main Jul 14, 2026
22 checks passed
@helly25
helly25 deleted the feat/hash-latency-benchmark-dist branch July 14, 2026 09:49
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.

2 participants