workshop private

← all creations

Streak

viz · created 2026-09-06

HyperLogLog counting unique visitors out of a request log — each address hashed into a coin-flip streak, 1024 registers keeping only the longest run each has seen, and a spotlight on any one of them showing that a single register can only ever answer in powers of two.

algorithmsinterview-prepcanvas

A log of visitor addresses arrives one request at a time and the question is the one every analytics page asks: how many of them were distinct? The honest answer needs a set, and a set costs memory in proportion to the answer. This counts them in 768 bytes that never grow.

Each address is hashed exactly once. The top 10 bits pick a register; the run of zero bits after them is a coin-flip streak, and each register keeps only the longest streak it has ever seen. That is the whole data structure — 1024 numbers between 0 and 33, six bits each — and the top of the screen shows one hash being cut in half and filed away. Pause and step to read a single one.

The piece is built around three things that are usually asserted rather than shown:

A repeat leaves no trace. The same address hashes the same way, lands in the same register, and wins the same streak, so a duplicate is not detected and does not need to be. Run the heavy repeats log — 6000 requests, a few thousand distinct — and watch the estimate ignore the difference. Deduplication here is not a feature that was added; it is a thing the structure cannot help doing.

One register is a terrible estimator. Press one register (or click any register in the array) and a red staircase joins the chart: what that register alone would claim, from its own longest streak. It moves in factors of two, because that is the only vocabulary a single maximum has — 1024, 2048, 4096, and off the top of the chart. The smooth teal line is the harmonic mean of a thousand of those staircases. Averaging is not a refinement of the trick, it is the trick.

The error band is a purchase, not a promise. The right chart draws the running error against ±1.04/√m, the published standard error. Drop to 16 registers — 12 bytes, a 1300× saving — and the band opens to ±26% while the estimate visibly staircases along with it. Go to 4096 and the band closes to ±1.6% for 3 KB. Changing the register count keeps the same log and the same position, so the two sketches are watching identical traffic and only the accuracy you paid for has changed.

The readout underneath carries the part that never moves: an exact set of 32-bit hashes against the sketch, and what both would cost at a billion distinct visitors — 3.7 GB against the same 768 B.

Reuse

src/streak.js is a framework-free ES module:

No rendering or timers in the module; the canvas demo is reference code.

Gotchas