From Leading Zeros to Cardinality
Imagine repeatedly flipping a fair coin until the first head. Seeing one tail is ordinary; seeing ten consecutive tails is rare. If the rarest run observed is very long, many trials probably occurred. HyperLogLog applies this idea to uniformly distributed hash bits: a long prefix of zeros is evidence that many distinct values have been seen.
One maximum is far too noisy, so HLL uses stochastic averaging. A hash is split into a register index and a remaining suffix. The index sends each distinct key to one of $m=2^p$ registers. In that register, HLL stores the maximum observed rank $\rho$, where $\rho$ is one plus the number of leading zeros in the suffix. Duplicate keys repeat the same hash and cannot increase the state after their first occurrence.
This deep dive builds on the prerequisite chapter about distinct elements and cardinality sketches. That chapter explains the problem and the max-leading-zero intuition. The gap here is the complete estimator: why register maxima are combined through a harmonic-like mean, how bias and boundary regimes are corrected, what the familiar $1.04/\sqrt m$ error means, and why distributed merging is a component-wise maximum rather than arithmetic addition.
Take $p=2$, so $m=4$. Suppose four hashed values have index/suffix pairs:
- register 0, suffix
001..., rank 3; - register 2, suffix
1..., rank 1; - register 0, suffix
0001..., rank 4; - register 3, suffix
01..., rank 2.
Starting from $[0,0,0,0]$, the registers become $[3,0,1,2]$. The second update to register 0 replaces 3 with 4 because registers retain maxima. Register 1 remains zero, which is valuable evidence that the cardinality is still small relative to the register count.
The principal terms are now concrete. Register maxima are the compressed observations. The harmonic mean language refers to aggregating $2^{M_j}$ through reciprocals $2^{-M_j}$, preventing one extreme register from dominating as an arithmetic mean would. Bias is systematic deviation of the raw estimator under finite $m$. Linear counting uses the number of zero registers in the small range. Saturation occurs when hash suffixes or register widths cannot represent a larger rank. Relative standard error describes run-to-run dispersion relative to true cardinality under the hash model.
HLL does not count long zero runs directly; it spreads keys across many registers, keeps one maximum per register, and combines reciprocal powers of those maxima. Its error guarantee depends on distinct canonical inputs behaving like uniform hashes—duplicates are harmless, but biased or adversarial hashes are not.
| Concept | Intuitive meaning | Exact example | Non-example or boundary | Main assumption | Question answered |
|---|---|---|---|---|---|
| Register maximum | Strongest rarity evidence in one substream | Update $M_j\leftarrow\max(M_j,\rho)$ | Sum of ranks in a register | Stable uniform hash and valid rank | What is the rarest suffix seen here? |
| Harmonic aggregation | Temper extreme maxima using reciprocals | $Z=\sum_j2^{-M_j}$ | Arithmetic mean of $2^{M_j}$ | Registers follow modeled occupancy | How should noisy substream estimates combine? |
| Stochastic averaging | Hash keys across $m$ parallel experiments | First $p$ bits choose one of $2^p$ registers | Round-robin by arrival order | Uniform register selection | How is single-maximum variance reduced? |
| Bias | Systematic finite-sample estimator error | Raw estimate corrected by calibrated regime | One unlucky run | Same implementation/model as calibration | Does average output miss the truth? |
| Linear counting | Infer small cardinality from empty registers | $m\ln(m/V)$ for $V$ zero registers | Applying it when $V=0$ | Uniform occupancy and small range | What works before most registers fill? |
| Saturation | Rank or hash space can no longer grow safely | Register capped at its encoded maximum | Merely a large but representable rank | Finite hash width and register width | When does upper-range bias appear? |
| Relative standard error | Typical error divided by truth | About $1.04/\sqrt m$ | Deterministic worst-case bound | Ideal hashes and central operating regime | How does precision scale with registers? |
From Leading Zeros to Cardinality
Use $p=2$, four registers, and the following index/rank observations: $(0,3),(2,1),(0,4),(3,2)$.
- Begin $M=[0,0,0,0]$.
- After $(0,3)$: $[3,0,0,0]$.
- After $(2,1)$: $[3,0,1,0]$.
- After $(0,4)$: $[4,0,1,0]$; register 0 keeps the maximum.
- After $(3,2)$: $[4,0,1,2]$.
- Compute $Z=2^{-4}+2^0+2^{-1}+2^{-2}=1.8125$.
- Using the illustrative small-$m$ constant $\alpha_4\approx0.568$, the raw estimate is $0.568\cdot16/1.8125\approx5.02$.
Expected result: the raw estimate is around 5 even though this tiny trace contains four observations; one register remains empty, so a real implementation may prefer a small-range correction. Reflection: why would averaging $2^{M_j}$ let one extreme register dominate?
Registers, Harmonic Means and Raw Estimates
Let a uniform $L$-bit hash be split into a $p$-bit prefix and a $q=L-p$ bit suffix. The prefix chooses $j\in\{0,\ldots,m-1\}$ with $m=2^p$. Define $\rho(w)$ as one plus the number of leading zeros in suffix $w$, capped according to the implementation. For each canonical key $x$,
$$ M_j\leftarrow\max(M_j,\rho(w)). $$
If the same key appears again, it maps to the same $j,w$, so the update is idempotent. This is why HLL estimates distinct keys rather than event count.
Within one register, a rank at least $r$ occurs with probability $2^{-(r-1)}$. A maximum near $r$ therefore suggests a substream cardinality on the scale of $2^r$. Directly averaging these exponentials is unstable: rare large registers dominate. HLL instead uses
$$ Z=\sum_{j=0}^{m-1}2^{-M_j}, \qquad E_{\mathrm{raw}}=\alpha_m\frac{m^2}{Z}. $$
This is proportional to the harmonic mean of the per-register scales $2^{M_j}$. The constant $\alpha_m$ corrects systematic behavior of the idealized register distribution. A traditional implementation uses $0.673,0.697,0.709$ for $m=16,32,64$, and approximately
$$ \alpha_m=\frac{0.7213}{1+1.079/m} $$
for larger $m$. Modern variants may use empirically calibrated bias tables or different estimators; constants and correction rules must travel with the serialized algorithm version.
The asymptotic relative standard error of classical HLL is about
$$ \operatorname{RSE}\approx\frac{1.04}{\sqrt m}. $$
Thus $p=14$ gives $m=16{,}384$ registers and approximate RSE $0.8125\%$. Doubling precision requires roughly four times as many registers. If registers use 6 bits, the dense payload is $98{,}304$ bits or 12 KiB, before headers and alignment.
The derivation requires near-uniform independent-looking hashes across both prefix and suffix, a correctly defined zero-count rank, enough hash width, and unsaturated registers. Using low-quality low bits for the index while the remaining bits are correlated is a counterexample: register load and ranks cease to follow the model even if the raw hash values look varied.
flowchart TD
A[Canonical distinct key] --> B[Uniform L-bit hash]
B --> C[Prefix chooses one of m registers]
B --> D[Suffix gives leading-zero rank rho]
C --> E[Update register by maximum]
D --> E
E --> F[Compute Z as sum of 2 to minus M]
F --> G[Raw estimate alpha m times m squared over Z]
G --> H[Expected RSE about 1.04 over square root m]
B --> X{Uniform split enough width compatible version?}
X -->|no| Y[Bias merge or saturation guarantee fails]
X -->|yes| C
classDef navy fill:#17365D,color:#fff,stroke:#17365D;
classDef teal fill:#147D84,color:#fff,stroke:#0D565B;
classDef purple fill:#6C3BAA,color:#fff,stroke:#472675;
classDef crimson fill:#C6284D,color:#fff,stroke:#861B35;
class A,B,C,D navy;
class E,F purple;
class G,H teal;
class X,Y crimson;
HLL converts each register maximum into reciprocal evidence $2^{-M_j}$, sums those values, and inverts the result with a calibrated $\alpha_m m^2$ scale. The classical raw estimator is strongest in its central regime; empty registers, finite hash space, and implementation-specific bias require explicit corrections rather than one universal formula.
Small-Range and Large-Range Corrections
The raw estimator behaves poorly when many registers are still zero. In the classical small range, let $V$ be the number of zero registers. Occupancy reasoning gives the linear-counting estimate
$$ E_{\mathrm{small}}=m\ln\left(\frac mV\right), $$
provided $V\gt0$. A traditional switching rule uses linear counting when the raw estimate is at most about $2.5m$ and zero registers remain. This threshold is historical and implementation-specific; HLL++-style systems may use sparse representations and empirically learned bias correction instead.
At the opposite extreme, a finite $L$-bit hash space has only $2^L$ possible values. Hash collisions then suppress observed distinctness. A classical large-range correction is
$$ E_{\mathrm{large}}=-2^L\ln\left(1-\frac{E_{\mathrm{raw}}}{2^L}\right), $$
often associated with a threshold near $2^L/30$. It is valid only while the logarithm's argument is positive and under its occupancy approximation. With 64-bit hashes, cardinalities approaching this regime require careful collision, numeric, and security analysis rather than blind formula use.
Register saturation is another large-range limit. With $q$ suffix bits, the largest observable zero run is finite. A packed register of width $r$ bits also caps the stored rank at $2^r-1$. The effective maximum is the smaller of the hash-derived and encoding-derived limits. Silent clipping causes downward bias.
Small-Range and Large-Range Corrections
Use $m=16$ registers with values $[0,0,0,0,1,1,1,2,2,2,3,3,3,4,4,5]$.
- Zero-register count is $V=4$.
- Compute reciprocal sum: $$Z=4+3(1/2)+3(1/4)+3(1/8)+2(1/16)+1/32=6.78125.$$
- With $\alpha_{16}=0.673$, raw estimate is $0.673\cdot16^2/6.78125\approx25.40$.
- Since $25.40\lt2.5m=40$ and $V\gt0$, classical linear counting gives $16\ln(16/4)=16\ln4\approx22.18$.
- Report the correction regime with the estimate; do not hide which formula produced it.
Perturbed case: change the four zero registers to 1. Then $V=0$, so linear counting is undefined. The implementation must use its raw/bias-corrected central estimator rather than evaluating $\ln(m/0)$.
| Regime or variant | Trigger/evidence | Estimator | Strength | Main assumption | Failure mode | Prefer when |
|---|---|---|---|---|---|---|
| Classical small range | Zero registers remain; traditional raw threshold near $2.5m$ | $m\ln(m/V)$ | Uses occupancy information efficiently | Uniform register assignment | Undefined at $V=0$; switch discontinuity | Cardinality is small relative to $m$ |
| Classical raw HLL | Central range | $\alpha_m m^2/\sum2^{-M_j}$ | Constant memory; RSE about $1.04/\sqrt m$ | Ideal hashes and calibrated constant | Finite-$m$ bias or bad hashes | Stable central operating range |
| Empirical bias correction | Implementation calibration domain | Raw estimate minus/interpolated bias | Better finite-range accuracy | Same version and calibration conditions | Table/version mismatch | Mature HLL++-style implementation |
| Classical large range | Estimate approaches finite hash space | $-2^L\ln(1-E/2^L)$ | Models hash collisions | Uniform $L$-bit occupancy | Invalid log, numeric cancellation, saturation | Documented extreme range only |
| Sparse representation | Few nonzero observations | Exact/sparse encoded hashes or registers | Smaller storage and accurate transition | Versioned sparse encoding | Conversion or merge bugs | Very small cardinality with large precision |
| Dense representation | Many registers active | Register array plus chosen estimator | Fast updates and merges | Register width sufficient | Packed-register saturation | Sustained medium/large cardinality |
Merging Cardinalities Across Partitions
HLL's merge operation follows directly from its state invariant. For compatible sketches A and B,
$$ M_j^{A\cup B}=\max(M_j^A,M_j^B) $$
for every register. The maximum is associative, commutative, and idempotent, so merge order and duplicate delivery do not change the result. Overlap is handled naturally because a repeated key contributes the same hash observation. Adding estimates is wrong whenever partitions overlap and discards register-level evidence even when they do not.
In a teaching case, two four-register sketches $[3,0,1,2]$ and $[1,4,1,0]$ merge to $[3,4,1,2]$. Neither vector addition nor averaging preserves the maximum-rank interpretation.
At professional scale, daily active-user sketches may be produced by many shards and merged across regions. Every sketch must share precision $p$, hash algorithm and seed, key canonicalization, register/rank convention, correction version, and time-window semantics. Headers should make incompatibility explicit. Downsampling higher precision to lower precision needs a proven conversion; blindly truncating arrays or merging different $m$ values is invalid.
Failure and adversarial cases center on hash trust and semantics. If tenants can choose keys against an exposed weak hash, they may concentrate registers or engineer extreme ranks. If one service hashes UTF-8 normalized IDs and another hashes raw bytes, their “same” users do not deduplicate. Hash-seed rotation prevents direct merging across versions. Window retries are harmless only when the same sketch update is idempotent at the key-hash level; misassigned windows change the target population.
Evidence that invalidates the design includes merge results differing by order, nonzero estimates for empty state, persistent bias versus exact shadow counts, register histograms inconsistent with uniform occupancy, saturation, incompatible header acceptance, or error far outside calibrated confidence bands.
flowchart TD
A[Define distinct identity and window] --> B[Fix hash seed precision and version]
B --> C[Build one HLL per partition]
C --> D[Validate compatibility headers]
D --> E{All contracts match?}
E -->|no| F[Reject or perform proven conversion]
E -->|yes| G[Merge each register by maximum]
G --> H[Compute raw union estimate]
H --> I[Apply one documented correction regime]
I --> J[Compare sampled windows with exact oracle]
J --> K{Bias RSE and saturation acceptable?}
K -->|yes| L[Deploy and monitor histograms]
K -->|no| M[Reject resize or repair hashing]
L --> N{Drift or version breach?}
N -->|yes| M
N -->|no| L
classDef navy fill:#17365D,color:#fff,stroke:#17365D;
classDef teal fill:#147D84,color:#fff,stroke:#0D565B;
classDef purple fill:#6C3BAA,color:#fff,stroke:#472675;
classDef crimson fill:#C6284D,color:#fff,stroke:#861B35;
class A,B,C,D navy;
class G,H,I purple;
class J,L teal;
class E,F,K,M,N crimson;
Merging Cardinalities Across Partitions: HyperLogLog Estimator & Corrections
Scenario. A global analytics service estimates daily active accounts across 40 regions. Expected union cardinality is $2\times10^9$, duplicate accounts appear in many regions, target RSE is at most $1\%$, and sketches must survive retries and rolling upgrades.
- Precision: solve $1.04/\sqrt m\le0.01$, giving $m\ge10{,}816$. Choose power-of-two $m=16{,}384$, hence $p=14$ and nominal RSE $0.8125\%$.
- Dense payload: with 6-bit registers, payload is 12 KiB per region before headers and packaging; verify the maximum encoded rank is sufficient for the 64-bit suffix.
- Compatibility header: include algorithm/correction version, $p$, hash width, hash identifier, seed ID, key canonicalization version, register width, and time-window ID.
- Merge: component-wise maximum across all compatible region sketches. Retries and overlapping users are idempotent. Never sum 40 regional estimates.
- Validation: maintain exact counts for sampled windows and synthetic known unions; test disjoint, fully overlapping, skewed, duplicate-heavy, empty, and adversarial key sets; run rolling-upgrade mismatch tests and register-saturation alarms.
- Expected observations: empirical relative standard deviation near the theoretical order, small-range corrections only in sparse test windows, merge-order invariance, and identical results under duplicate deliveries.
- Invalidation evidence: sustained bias above $0.3\%$, empirical RSE above $1\%$, incompatible sketches accepted, nonuniform register occupancy, or any saturation.
Selection decision: deploy $p=14$ HLL only with strict compatibility rejection and exact-shadow calibration. Increase $p$ if the full error budget includes less than $0.8125\%$ sketch noise; change hash or threat controls if adversarial keys can violate uniformity.
Implement and Validate HyperLogLog
Implementation quality depends on bit conventions that prose often hides. Specify whether prefix or suffix selects the register, whether $\rho$ starts at 1, how an all-zero suffix is ranked, how registers pack across words, and which correction table/version is used. Golden vectors should verify hashes, indices, ranks, serialized bytes, merges, and estimates across languages.
This bridges backward to distinct counting and maximum-rank sketches, and forward to HLL++, sparse encodings, intersection estimation, set sketches, privacy-preserving telemetry, and distributed sketch governance. HLL estimates unions naturally; intersections obtained by subtracting noisy union estimates can be unstable and require separate analysis.
Practice: Implement and Validate HyperLogLog
Starter configuration: 64-bit hashes, $p=10$, $m=1024$, 6-bit registers, and test cardinalities $0,100,1{,}000,10{,}000,100{,}000$.
Tier 1 — Hand trace
Given six fixed hash bit strings, split each into 10-bit index and 54-bit suffix, compute $\rho$, and update the chosen register. Include a duplicate and prove it leaves state unchanged.
Expected artifact: table of key, hash, index, suffix prefix, rank, register before, and register after. Completion criterion: all-zero suffix handling is explicit.
Tier 2 — Estimator calculation
For a supplied register vector, compute $Z$, $\alpha_m$, raw estimate, zero count $V$, and selected correction. Recompute after changing one maximum to show the harmonic response.
Debugging prompt: if empty registers contribute zero to $Z$, recall that $2^0=1$.
Tier 3 — Accuracy experiment
Run at least 500 independent seeded trials for several cardinalities. Report mean relative bias, relative standard deviation, RMSE, 5th/95th percentiles, regime-selection frequency, and compare central-range SD with $1.04/\sqrt{1024}=3.25\%$.
Tier 4 — Merge and fault tests
Verify commutativity, associativity, and idempotence of register-wise maximum. Test disjoint and overlapping partitions against a centralized sketch. Reject mismatched $p$, hash width, seed, canonicalization, and correction version. Inject register clipping, byte corruption, poor low-bit hashes, seed rotation, and window mismatch.
Completion criterion: all valid merge orders serialize identically; every incompatible header is rejected; no supported input creates a false claim of compatibility.
Tier 5 — Professional judgment
Choose precision and representation for per-minute IoT devices, daily active users, and a hostile public multi-tenant API. Include logical and allocated memory, hash cost, error budget, sparse/dense transition, merge topology, retention, version migration, and evidence that would reverse the choice.
Stretch goal: quantify why estimating a small intersection as $|A|+|B|-|A\cup B|$ can have high relative error even when each HLL has low RSE.
Rubric (10 points): trace conventions 2; raw/corrected calculation 2; empirical validation 2; merge/fault tests 2; production design 2. Mastery requires at least 8 points and no merging of estimates in place of registers.
Reflection: is the dominant risk stochastic HLL error, hash/model bias, incompatible merges, or target-definition drift?
Decision checklist: canonicalize identity, use a versioned uniform hash, size $m$ from the error budget, preserve register/rank conventions, apply documented correction regimes, merge compatible registers by maximum, monitor zero counts and saturation, and validate against exact shadows. HLL excels at mergeable unions, but it does not repair bad identity semantics or make small intersections precise.