The floors

The floor under a summary

An exact one-pass distinct-counter over a universe of u keys needs at least log2 of u-choose-u-over-2 bits of state — the same counting argument as the sorting floor, applied to memory states instead of outcomes. At u = 12 that is 9.85 bits, and an eight-bit candidate is shown to collide by running all 924 subsets.

The first floor on this site counts outcomes. A comparison sort must be able to distinguish n!n! orderings; each comparison distinguishes two cases; so no comparison sort makes fewer than log2(n!)\log_2(n!) comparisons. It is exact, computable, and it bounds a resource — comparisons — that the algorithm spends.

The floor here counts something else. It bounds a resource the algorithm holds, and it is the same argument with memory states in place of outcomes.

Bits of state an exact distinct-counter needs, universe 8 to 20The middle line is log₂ C(u, u/2), the exact floor: a one-pass algorithm that answers the distinct count exactly must reach a different memory state for every half-sized subset of the universe, because two subsets sharing a state give the same answer after one more key is appended and their true answers differ. The upper line is the u-bit bitmap that achieves it. The lower line is ⌈log₂(u+1)⌉, the space a plain counter takes — always below the floor, which is why no plain counter is exact. At u = 12 the floor is 9.85 bits, and a candidate holding 8 was run over all 924 subsets: two of them reached the same state, and appending one key that is in one and not the other leaves answers of 6 and 7 that it cannot tell apart.011228101214161820universe size ubits of statea u-bit bitmaplog₂ C(u, u/2)⌈log₂(u+1)⌉, a counterat u = 12: 924 subsets, 8 bitstwo collide → answers 6 and 7floor computed exactly · collision found by exhaustion at u = 12floor 9.85 bits
Fig. 1 The floor, computed exactly across a range of universe sizes, with the collision it forces performed rather than quoted. The middle line is log2(uu/2)\log_2\binom{u}{u/2}. Above it is the uu-bit bitmap that achieves it; below it is the space a plain counter takes, which is why no plain counter can be exact. At u=12u = 12 the floor is 9.85 bits, and every one of the 924 half-sized subsets was run through an eight-bit candidate until two of them landed in the same state.

The argument, in four lines

Fix a universe of uu keys. Restrict attention to streams that consist of the elements of some subset SS of size u/2u/2, in any order.

Suppose a one-pass algorithm answers the distinct count exactly, and suppose two different such subsets STS \ne T leave it in the same memory state. Take a key xx that is in SS and not in TT — one exists, because the two subsets are the same size and are different — and append it to both streams.

From that point on the algorithm sees identical input from identical state, so it ends in identical state and gives an identical answer. But the true answers differ: S{x}S \cup \{x\} has u/2u/2 distinct keys and T{x}T \cup \{x\} has u/2+1u/2 + 1.

So no two of the (uu/2)\binom{u}{u/2} subsets may share a state, the state must take at least that many values, and the memory must hold at least log2(uu/2)\log_2\binom{u}{u/2} bits.

Nothing in that depends on how the algorithm works. It is not about hashing, or about which statistic is kept, or about cleverness — it is a counting argument over memory states, and it applies to every algorithm at once in exactly the way the sorting floor applies to every comparison sort at once.

Performing the pigeonhole

Quoting a pigeonhole argument is cheap. The habit this site runs on is that a claim gets a test it could fail, so the collision is found rather than asserted.

At u=12u = 12 there are (126)=924\binom{12}{6} = 924 half-sized subsets and the floor is log2924=9.85\log_2 924 = 9.85 bits. A candidate algorithm holding eight bits — a bitmap of the first eight keys, which is a reasonable thing for a small exact counter to keep — is run over all 924, its final state recorded for each, and the states compared.

Two subsets collide. The witness is complete: the two streams, the shared state, the key to append, and two true answers of 6 and 7 that the algorithm answers identically. That is a refutation rather than an existence claim.

The second half of the check is the one that makes the first mean anything. The same exhaustive search is run against a candidate holding twelve bits — enough for the whole universe — and it must not collide, and it does not: 924 subsets, 924 distinct states. A floor that fired on everything would be a bug rather than a bound, and this is the check that says so. A third candidate, one that keeps only the running count, collides immediately, which it must.

What the number looks like

log2(uu/2)\log_2\binom{u}{u/2} is u12log2uO(1)u - \tfrac12\log_2 u - O(1) — linear in the universe, with a small logarithmic discount.

universe uu floor, bits a uu-bit bitmap a plain counter
8 6.13 8 4
12 9.85 12 4
16 13.65 16 5
24 21.37 24 5
32 29.16 32 6
64 60.67 64 7

The bitmap is within a few per cent of the floor at every size, so the floor is essentially tight and the obvious algorithm is essentially optimal. There is nothing to find here — which is the useful conclusion, because it says the exact problem is closed and any progress has to come from changing the problem.

That is the same shape as the sorting floor’s aftermath. How close anything gets to the floor measures the gap between the best sorts and log2(n!)\log_2(n!) and finds it small, and the interesting work moves to constants and to different models rather than to better comparison sorts.

Changing the problem

Every structure in this phase gets under that floor, and none of them violates it. They answer a different question.

Allow the answer to be within a relative ε\varepsilon and to be that wrong with probability at most δ\delta, and the requirement drops from linear in the universe to O(ε2+logu)O(\varepsilon^{-2} + \log u) bits — a few thousand, permanently, whatever uu is. A HyperLogLog of 5,120 bits counts distinct keys drawn from a universe of four billion to within 3.4%, and the exact floor for that universe is four billion bits.

The size of that gap is the whole justification for the field. It is not a marginal saving; it is the difference between a structure that fits in a cache line and one that does not fit anywhere.

The approximate floor, and what is not claimed

There is a lower bound for the approximate problem too: Ω(ε2)\Omega(\varepsilon^{-2}) bits, from Indyk and Woodruff and sharpened since, and it is a communication-complexity argument rather than a counting one.

It is not demonstrated here. Quoting it while pretending to have measured it would be exactly the failure this site exists to avoid, and the argument is not one that a small exhaustive search performs. What is measured is the shape: every estimator in this field climbs an ε2\varepsilon^{-2} curve, and none of them climbs a cheaper one.

That distinction is worth making carefully, because it is the difference between two kinds of statement. The exact floor above is a theorem verified here at small uu, by exhaustion. The approximate floor is a theorem quoted here, alongside a measurement of whether the structures behave as though it binds them. Both are honest and they are not the same, and the plate for each says which it is.

The measured version: fitting log-bits against log-accuracy across four HyperLogLog designs gives an exponent of 1.89 where the shape says 2. That is a measurement of the structures rather than of the bound — a better structure could sit lower on the same slope, and no structure of any kind can sit on a shallower one if the bound is right.

Why half-sized subsets

The restriction to subsets of size u/2u/2 looks like a technicality and is load-bearing, which is worth a paragraph because getting it wrong produces an argument that does not close.

The obvious version of the proof takes any two distinct subsets STS \ne T sharing a state and appends a key xSTx \in S \setminus T. Then S{x}S \cup \{x\} has S|S| distinct keys and T{x}T \cup \{x\} has T+1|T| + 1 — and if S=T+1|S| = |T| + 1 those are the same number, so the two streams have the same true answer and no contradiction follows. The general argument fails.

Fixing every subset to the same size u/2u/2 removes the escape: S=T=u/2|S| = |T| = u/2, so the two answers are u/2u/2 and u/2+1u/2 + 1 and always differ. The cost is that the bound counts (uu/2)\binom{u}{u/2} states rather than 2u2^u, which is a discount of half a logarithm and does not change the shape.

This is the same care the sorting floor’s derivation needs and gets. log2(n!)\log_2(n!) counts orderings rather than arrays because two arrays with the same ordering are indistinguishable to a comparison sort, and counting arrays would give a bound that is both larger and wrong. A counting argument is only as good as the set it counts.

Bits of state an exact distinct-counter needs, universe 10 to 30The middle line is log₂ C(u, u/2), the exact floor: a one-pass algorithm that answers the distinct count exactly must reach a different memory state for every half-sized subset of the universe, because two subsets sharing a state give the same answer after one more key is appended and their true answers differ. The upper line is the u-bit bitmap that achieves it. The lower line is ⌈log₂(u+1)⌉, the space a plain counter takes — always below the floor, which is why no plain counter is exact. At u = 14 the floor is 11.74 bits, and a candidate holding 10 was run over all 3,432 subsets: two of them reached the same state, and appending one key that is in one and not the other leaves answers of 7 and 8 that it cannot tell apart.01733101418222630universe size ubits of statea u-bit bitmaplog₂ C(u, u/2)⌈log₂(u+1)⌉, a counterat u = 14: 3,432 subsets, 10 bitstwo collide → answers 7 and 8floor computed exactly · collision found by exhaustion at u = 14floor 11.74 bits
Fig. 2 The same floor over a larger range, with the exhaustive collision search run at u=14u = 14 against a ten-bit candidate: 3,432 half-sized subsets, ten bits of state, and the pigeonhole fires. What is worth reading off the plate is the gap between the middle line and the top one, which is the half-logarithm the size restriction costs — and how little difference it makes, which is why the bitmap is essentially optimal.

The third kind of lower bound on this site

There are now three, and they are worth naming together because the shapes of lower-bound arguments are not obvious from a single example.

Leaf counting. A comparison sort’s decision tree must have n!n! leaves and a binary tree of height hh has at most 2h2^h of them. Counts outcomes, bounds operations. The floor under every comparison sort.

The adversary. An algorithm deciding connectivity can be watched: whatever edges it has examined, an adversary can place the answer in one it has not, so it must examine them all. Counts nothing, bounds operations, and works by playing against the algorithm rather than by counting anything. The adversary who hides the edge.

State counting. A one-pass algorithm’s memory must distinguish every input whose continuation would separate them. Counts memory states, bounds space.

The third is the one that generalises furthest, and it is the ancestor of every space lower bound in the streaming literature. The general form replaces “two subsets” with “two inputs to a two-party communication problem”, and the memory state becomes a message; the counting becomes a bound on how much has to be communicated. Everything in that literature is this argument with more machinery.

The same argument at three universes

The floor is log2(uu/2)\log_2\binom{u}{u/2} and the demonstration is an exhaustive search over subsets, so both can simply be run again at other sizes.

Bits of state an exact distinct-counter needs, universe 8 to 16The middle line is log₂ C(u, u/2), the exact floor: a one-pass algorithm that answers the distinct count exactly must reach a different memory state for every half-sized subset of the universe, because two subsets sharing a state give the same answer after one more key is appended and their true answers differ. The upper line is the u-bit bitmap that achieves it. The lower line is ⌈log₂(u+1)⌉, the space a plain counter takes — always below the floor, which is why no plain counter is exact. At u = 10 the floor is 7.98 bits, and a candidate holding 8 was run over all 252 subsets: two of them reached the same state, and appending one key that is in one and not the other leaves answers of 5 and 6 that it cannot tell apart.0918810121416universe size ubits of statea u-bit bitmaplog₂ C(u, u/2)⌈log₂(u+1)⌉, a counterat u = 10: 252 subsets, 8 bitstwo collide → answers 5 and 6floor computed exactly · collision found by exhaustion at u = 10floor 7.98 bits
Fig. 3 A shorter sweep with the collision demonstrated at a ten-element universe rather than twelve. The middle line is the exact floor; the demonstration below it produces the two subsets a candidate cannot tell apart.
Bits of state an exact distinct-counter needs, universe 8 to 20The middle line is log₂ C(u, u/2), the exact floor: a one-pass algorithm that answers the distinct count exactly must reach a different memory state for every half-sized subset of the universe, because two subsets sharing a state give the same answer after one more key is appended and their true answers differ. The upper line is the u-bit bitmap that achieves it. The lower line is ⌈log₂(u+1)⌉, the space a plain counter takes — always below the floor, which is why no plain counter is exact. At u = 12 the floor is 9.85 bits, and a candidate holding 6 was run over all 924 subsets: two of them reached the same state, and appending one key that is in one and not the other leaves answers of 6 and 7 that it cannot tell apart.011228101214161820universe size ubits of statea u-bit bitmaplog₂ C(u, u/2)⌈log₂(u+1)⌉, a counterat u = 12: 924 subsets, 6 bitstwo collide → answers 6 and 7floor computed exactly · collision found by exhaustion at u = 12floor 9.85 bits
Fig. 4 The original sweep with the candidate given six bits rather than eight — four bits under the floor rather than two. The collision is found sooner and involves more pairs, which is what being further under a counting bound means.

Moving the sweep upward is the third variation, and it is the one that says the argument is not about universes small enough to enumerate — the demonstration is, and the floor is not.

Bits of state an exact distinct-counter needs, universe 10 to 22The middle line is log₂ C(u, u/2), the exact floor: a one-pass algorithm that answers the distinct count exactly must reach a different memory state for every half-sized subset of the universe, because two subsets sharing a state give the same answer after one more key is appended and their true answers differ. The upper line is the u-bit bitmap that achieves it. The lower line is ⌈log₂(u+1)⌉, the space a plain counter takes — always below the floor, which is why no plain counter is exact. At u = 14 the floor is 11.74 bits, and a candidate holding 10 was run over all 3,432 subsets: two of them reached the same state, and appending one key that is in one and not the other leaves answers of 7 and 8 that it cannot tell apart.0122410121416182022universe size ubits of statea u-bit bitmaplog₂ C(u, u/2)⌈log₂(u+1)⌉, a counterat u = 14: 3,432 subsets, 10 bitstwo collide → answers 7 and 8floor computed exactly · collision found by exhaustion at u = 14floor 11.74 bits
Fig. 5 And the sweep moved up: universes from 1,024 to four million, with the demonstration at fourteen. The floor is a lower bound at every point of every one of these plates, and at every point it is computed rather than estimated.

What the floor does not say

Two things, and both are the usual caveats sharpened by the setting.

It says nothing about a particular algorithm. A structure using far more than the floor is not thereby bad, and one at the floor is not thereby good at anything else. The bitmap that achieves this floor is useless in practice for the reason the floor makes clear — it needs a bit per possible key, and real universes are 128-bit identifiers.

It says nothing about approximate answers, and that is where all the engineering is. Which is the most useful thing about it. A floor that closes off the exact problem entirely is a floor that tells everybody where to go instead, and the entire field of summaries is the answer to this one.

256 HyperLogLog registers after 9,334 distinct keysOne bar per register. A key's hash picks the register by its first 8 bits and offers it the position of the leftmost 1 in the rest; the register keeps the largest it has ever been offered. The tallest here is 17, which means some key hashed to 16 leading zeros — evidence of roughly 2^16 distinct keys in that register's share of the stream. The harmonic mean of 2^register over all 256 of them, scaled by α, estimates 8,531 against a true 9,334: an error of -8.61%. Each register holds five bits, so the whole structure is 1,280 bits.0917leading-zero rank keptregister, 0 to 255estimate 8,531truth 9,334error -8.61%0 still empty256 registers × 5 bits = 1,280 bitspredicted ±6.50%
Fig. 6 The structure that lives under the floor by changing the question. Two hundred and fifty-six five-bit registers — 1,280 bits — summarising a stream drawn from a universe of thirty-two thousand keys, whose exact floor is a little under thirty-two thousand bits. The saving is a factor of twenty-five here and it grows without limit: widen the universe to four billion and the floor follows it, while this picture does not change at all.

What is actually being spent

One more reading of the floor is worth having, because it explains why the approximate problem is so much cheaper rather than merely stating that it is.

The exact answer has to distinguish (uu/2)\binom{u}{u/2} inputs. The approximate answer has to distinguish only the answers that are more than ε\varepsilon apart, and on a range from 1 to uu there are about lnu/ε\ln u / \varepsilon of those. The logarithm of that is loglogu+log(1/ε)\log\log u + \log(1/\varepsilon) — a handful of bits.

That is not the whole story, because the algorithm also has to be right with probability 1δ1-\delta against an input it cannot see coming, and the ε2\varepsilon^{-2} in every real bound comes from that rather than from the number of distinguishable answers. But it locates the saving correctly: the exact problem is expensive because of how many inputs there are, and the approximate problem is cheap because of how few answers there are. Every summary in this phase is exploiting the second number, and the first number is what the floor counts.

There is a version of the same statement for the frequency half. Answering “how often did key xx occur” exactly, for arbitrary xx, requires distinguishing every possible frequency vector and is linear in the universe by the same argument. Count-Min’s escape is the same escape: give up on the tail, be additively wrong by a share of the stream, and the requirement collapses to a few thousand bits. The floor is not a limit on what can be built; it is a statement about which question was being asked.

Relative error against a key's true count, 4×64 sketchOne mark per distinct key in a Zipf stream of 60,000 items. The horizontal position is how often that key really occurred; the vertical is how far above the truth the sketch's estimate is, as a fraction of the truth. The fall is almost exactly a slope of −1, because the sketch's error is a fixed number of counts — about 2,548 here, being e/w of the whole stream — divided by whatever the key's own count happens to be. The heaviest key is over by 4.11% and the rarest by 34100%: the same sketch, the same query, and a factor of 8,290 between them.1101001,0000.111010010³true count of the keyrelative errorheaviest keyrarest key4×64 counters · 8,192 bits · Zipf s = 1.1 · 3,528 distinct keys at 702 positions4.11% to 34100%
Fig. 7 The frequency half’s escape, drawn as what it costs. The structure is small because it has stopped trying to be right about the left-hand end of this plot, where the relative error runs into the thousands of per cent. That is not a failure of the sketch; it is the purchase. A structure that was right there would be paying the linear floor, and the whole of the saving is visible as the height of the marks it has given up on.

The floor names a universe, and it names a stream length too

The comparison that opens the section on changing the problem — a few thousand bits against four billion — is the right order of magnitude for the question it asks and it is not the right comparison for most deployments, and the difference is a clause in the argument rather than a defect in it.

The counting argument restricts attention to subsets of size u/2u/2. A stream realising one of those contains two billion distinct keys when the universe is four billion. So the four-billion-bit floor is a statement about an algorithm that must be exact on streams containing up to half the universe — and a deployment counting twenty thousand distinct visitors out of a four-billion-key identifier space is not being asked for anything of the kind.

Redo the count with the stream length in it. An algorithm exact on streams of at most dd distinct keys must distinguish the (ud)\binom{u}{d} subsets of that size, which for dd far below uu is about

d(log2ud+log2e) bitsd\left(\log_2 \frac{u}{d} + \log_2 e\right) \text{ bits}

— roughly nineteen bits per distinct key at u=232u = 2^{32} and d=20,000d = 20{,}000, so about 380,000 bits in total. That is the honest floor for that workload, it is four orders of magnitude below the headline figure, and it is still 75 times what the HyperLogLog on the same plate spends.

Which is a smaller saving and a better argument. A factor of a million invites the reading that exact counting is impossible, and it is not — 380,000 bits is 47 kilobytes, which is nothing, and any system counting twenty thousand things can simply keep them. A factor of 75 is the real trade and it is the one that decides deployments: the summary wins because it holds while the cardinality grows without anybody having sized for it, not because the exact structure could never have been afforded.

The general lesson is the one this collection keeps arriving at from different directions. A bound quoted with one of its parameters left at its worst case is a bound about a workload nobody has, and the repair is the same as everywhere else: name the parameters, all of them, and recompute. The universe size was named on every plate here from the start. The stream length was the one that was not, and it is in the floor just as firmly.

What the argument asks of the algorithm, which is very little

One feature of this floor is worth separating out, because it makes the bound stronger than its neighbours in a way the family table does not show.

The construction appends a single key and asks once, at the end. It does not require the algorithm to answer after every arrival, it does not require the answer to be available at any intermediate point, and it does not care how much computation happens when the query comes. All it needs is that two streams reaching the same state produce the same final answer, which is true of any deterministic procedure whatever.

Compare that with the windowed floor, whose statement includes an answer after every arrival, or with the multi-pass constructions, which are about how many times the input may be read. Those bounds buy their strength partly from what they demand of the algorithm. This one demands almost nothing and still comes out linear in the number of distinct keys.

That is worth knowing when reading the family table above, because it says which floors would survive a change of setting. Relax the windowed floor’s requirement to a single query at the end and it weakens immediately — an algorithm told in advance that it will be asked once can defer. Relax this one and nothing happens, because it was never using the requirement. A bound that leans on a strong assumption is a bound to check against a deployment that may not make it, and this is the rarer kind that does not lean on anything.

Why a floor is worth having

The site’s position on floors has been consistent across three fields and is worth restating where it applies to a resource rather than to an operation count.

A floor turns “nobody has found anything better” into “there is nothing better”, which is a different kind of statement and closes a line of enquiry. It also gives every algorithm a denominator: the gap between a structure and its floor is a number, and how close anything gets to the floor is the essay about reading it. A structure at 1.02 times the floor is finished; one at 40 times it is an invitation.

Here the exact floor is achieved to within a few per cent by the obvious algorithm, so the denominator says the exact problem is done. And that is precisely the information that sends the whole field somewhere else — into a relaxed problem whose own floor is known only up to a shape, where the structures are within a constant of that shape, and where the interesting question stops being how few bits and starts being what the bits are allowed to be wrong about.

What this makes readable

Essays that name this one as a prerequisite.

Named alongside this one

Essays reaching for the same objects. Nobody chose these; they are what the concept index makes visible.

What links here

The 8 essays that link to this one and share the most of its objects, of 9 that link here.

The objects this essay names

Each one links to every other essay that touches it.

Adversarial inputCardinalityCounting argumentGuaranteeHyperLogLogInformation-theoretic boundLower boundPigeonholeSketchSpace lower boundState bitsStreaming algorithm