When the algorithm flips a coin

Two hashes that shared their low bits

Two pages on blocked Bloom filters with thresholds each recorded an instability they could not explain: a false-positive rate that collapsed on one seed at 256-bit blocks, and a pair of four-bit thresholds measuring 0.169% where its neighbours measured 0.08%. Both came from how a hash was brought into range. Every filter took its block and its ordering value as a modulo of a multiply-shift hash, and the low bits of such a hash depend only on the low bits of the key, so the two values were dependent whenever the block count had a factor of two to spare. At 992 blocks the threshold filter measures anything from 0.185% to 0.645%; read from the hash's top bits, 0.126% to 0.133%.

A block the lookup can work out gave a blocked Bloom filter a threshold for each block. A key is placed in its first block while its ordering value, a second hash of the key, is below that block’s threshold, and in a second block otherwise. A lookup reads the threshold and knows which block to check. The bits a second threshold costs shrank the thresholds from eight bits to four, and a threshold knows only its own block tried sharing one among a group of blocks. Each of the last two pages recorded something it could not explain. The first measured two four-bit thresholds at 256-bit blocks at 0.169%, beside neighbours near 0.08%. The second centred itself on 512-bit blocks because at 256 bits one seed of four collapsed, and it said so.

The last of those pages closed by proposing to code the threshold table by its own distribution, which would save about a third of the table: half a per cent of a filter’s memory. A saving that size moves the false-positive rate by a few per cent at most, and an instability that doubles the rate on one seed in four would bury it. So the instability had to be traced before the saving could be measured. It traces to one line that every one of these filters shares, the line that turns a hash into a block number.

The reduction, and what it was defended on

Every filter on these pages hashes a key with multiply-shift. The hash multiplies the key by an odd constant modulo 2322^{32} and keeps the top 30 bits of the product. A block number is that 30-bit value modulo the number of blocks, and the ordering value is another such hash modulo sixteen. The modulo was chosen with an argument, and the argument was about bias: at these sizes it introduces a bias below one part in a million, since 2302^{30} is so much larger than any block count, and none at all when the count is a power of two. That is true, and it answers the wrong question. Bias is about one value’s distribution, and the trouble here is two values’ dependence.

The low bits of a product depend only on the low bits of its factors. Bit jj of a⋅x mod 232a \cdot x \bmod 2^{32} is a function of bits 0 to jj of aa and of xx, and nothing above. Keeping the top 30 bits drops the lowest two, so the lowest jj bits of the hash are a function of the key’s lowest j+2j+2 bits. A modulo by sixteen keeps exactly the lowest four bits. A modulo by 992, which is 31 times 32, keeps among other things the value modulo 32, the lowest five bits. So a key’s ordering value and its first block modulo 32 are both functions of the key’s lowest seven bits, through two different multipliers. Among all keys they take at most 128 combinations of the 512 that independent values would reach.

A hash is a family, not a function showed a hash that takes the low bits of the key sending every multiple of the table size to one bucket. Multiply-shift fixes that for one value, by keeping the top bits of the product, which depend on every bit of the key. It does not fix it for the low bits of its own output, and no multiplier can, because carries only move upward.

Sixty-four cells of two hundred and fifty-six

Two values of one key that should be independent: over 262,144 random keys, the ordering value u (0 to 15) and the first block modulo 16 reach only 64 of the 256 combinations when both are taken by a modulo of a multiply-shift hash, and all 256 when both are taken from the top bits; at 256 blocks the pair of blocks a key may use takes 1,024 values instead of 64,313 of 65,536Two 16-by-16 grids of cells, rows the ordering value u from 0 to 15, columns the first block's index modulo 16, each cell shaded by how many of 262,144 random 32-bit keys land in it. Left: both values are the 30-bit multiply-shift hash reduced by a modulo, as the published threshold filters reduce them; 64 cells are reached and the rest are empty, because the low bits of a multiply-shift hash are a function of the key's low bits alone. Right: both are taken from the hash's top bits; 256 cells are reached, evenly. Separately, the pair of blocks (first, second) at 256 blocks takes 1,024 distinct values by modulo and 64,313 by top bits, of 65,536 possible.Reduced by a modulofirst block, mod 16u64 of 256 cells reachedReduced by its top bitsfirst block, mod 16u256 of 256 cells reachedshade: keys a cell receives; pale: none262,144 random keys
Fig. 1 Over 262,144 random keys, the ordering value against the first block modulo 16. By a modulo of the hash: 64 of the 256 combinations are reached. From the hash’s top bits: all 256, evenly. At 256 blocks, the pair of blocks a key may use takes 1,024 values by modulo and 64,313 from the top bits, of 65,536 possible.

Taken by a modulo, a key’s ordering value and its first block modulo 16 reach 64 of the 256 combinations; taken from the hash’s top bits, all 256. Both values are functions of the key’s lowest six bits, and six bits have 64 values, so the grid on the left has exactly 64 cells filled and every one of them receives four times its share. Each residue of the block index sees only four of the sixteen ordering values. The top bits of a multiply-shift hash depend on every bit of the key, and the grid on the right is flat.

The same holds for a key’s two block choices. At 256 blocks the first and second block, each the lowest eight bits of a different multiply-shift hash, are both functions of the key’s lowest ten bits. So the pair takes 1,024 values of the 65,536 possible. Keys are not spread over all pairs of blocks; they come in 1,024 kinds, each kind sharing the same two blocks.

Where the collapse came from

The instability was the reduction: a four-bit threshold filter at 16 bits a key, over eight seeds — at 128-bit blocks (992 blocks, a multiple of 32) the modulo gives 0.185% to 0.645% and the top bits 0.126% to 0.133%; at 256-bit blocks (504, a multiple of 8) 0.082% to 0.171% against 0.072% to 0.081%; at 64 bits (1927 blocks, odd) the two agreeFalse-positive rate of the one-threshold blocked filter, 8,192 keys at 16 bits a key, four-bit thresholds, eight filters and 150,000 absent queries a seed, for eight seeds, at four block widths, both reductions. 64-bit blocks, 1927 blocks (largest power of two dividing it: 1): modulo 0.331%, 0.329%, 0.317%, 0.312%, 0.329%, 0.322%, 0.328%, 0.310%; top bits 0.324%, 0.318%, 0.326%, 0.323%, 0.317%, 0.325%, 0.310%, 0.331%. 128-bit blocks, 992 blocks (largest power of two dividing it: 32): modulo 0.197%, 0.348%, 0.645%, 0.223%, 0.244%, 0.416%, 0.402%, 0.185%; top bits 0.126%, 0.128%, 0.126%, 0.133%, 0.127%, 0.133%, 0.132%, 0.131%. 256-bit blocks, 504 blocks (largest power of two dividing it: 8): modulo 0.086%, 0.107%, 0.171%, 0.083%, 0.127%, 0.097%, 0.092%, 0.082%; top bits 0.076%, 0.074%, 0.080%, 0.081%, 0.076%, 0.077%, 0.072%, 0.075%. 512-bit blocks, 254 blocks (largest power of two dividing it: 2): modulo 0.063%, 0.061%, 0.062%, 0.062%, 0.057%, 0.060%, 0.065%, 0.063%; top bits 0.061%, 0.059%, 0.059%, 0.061%, 0.059%, 0.059%, 0.057%, 0.059%.0.0%0.1%0.2%0.3%0.4%0.5%0.6%false-positive rate64-bit blocks1927 blocks128-bit blocks992 blocks256-bit blocks504 blocks512-bit blocks254 blocksreduced by a moduloreduced by its top bitseach dot: one seedupper row of a pair: modulo; lower: top bits
Fig. 2 The one-threshold filter with four-bit thresholds, 16 bits a key, over eight seeds. At 128-bit blocks (992 blocks, a multiple of 32): 0.185% to 0.645% by modulo, 0.126% to 0.133% from the top bits. At 256-bit blocks (504, a multiple of 8): 0.082% to 0.171% against 0.072% to 0.081%. At 512 bits (254 blocks): 0.057% to 0.065% against 0.057% to 0.061%. At 64 bits (1,927 blocks, odd): the same both ways.

At 128-bit blocks the modulo filter’s rate runs from 0.185% to 0.645% across eight seeds; the same filter reading the hash’s top bits runs from 0.126% to 0.133%. The spread between seeds is a factor of 3.5 in one and 1.06 in the other, and the top-bit filter is better than the modulo filter’s best seed. At 256-bit blocks the modulo filter runs from 0.082% to 0.171%, which is the collapse the previous page saw on one seed of four, and the top-bit filter from 0.072% to 0.081%. At 512-bit blocks the two nearly agree, and at 64-bit blocks they agree to within the seeds’ own spread.

The block counts say why the widths differ. Sixteen bits a key over 8,192 keys is 131,072 bits, and with a four-bit threshold a block the filter holds 1,927 blocks of 64 bits, 992 of 128, 504 of 256 and 254 of 512. Those are an odd number, 31 times 32, 63 times 8 and 127 times 2. The dependence between the ordering value and the block needs a common power of two, and the larger the power of two in the block count, the more of the block index is tied to the key’s low bits. A count of 992 ties five bits of the block to the same seven key bits that set the ordering value. A count of 254 ties one bit, and the filter barely notices. An odd count ties nothing.

The rate follows the power of two

The rate follows the block count's power of two: at 128-bit blocks and four-bit thresholds, the modulo filter's rate is 0.131% on average where the count is odd or twice an odd number, and 0.190% at 976 blocks (a multiple of 16), 0.146% at 984 blocks (a multiple of 8), 0.197% at 992 blocks (a multiple of 32); reduced by its top bits the filter stays between 0.124% and 0.138% at every countFalse-positive rate of the one-threshold blocked filter at 128-bit blocks, four-bit thresholds and 16 bits a key, for filters of 8,000 to 8,200 keys in steps of eight, which gives block counts from 969 to 993. Reduced by a modulo: 969 0.133%, 970 0.130%, 971 0.136%, 972 0.135%, 973 0.125%, 974 0.132%, 975 0.137%, 976 0.190%, 977 0.128%, 978 0.126%, 979 0.124%, 980 0.133%, 981 0.126%, 982 0.136%, 983 0.132%, 984 0.146%, 985 0.127%, 986 0.134%, 987 0.133%, 988 0.127%, 989 0.134%, 990 0.133%, 991 0.128%, 992 0.197%, 993 0.132%. Reduced by its top bits: 969 0.129%, 970 0.129%, 971 0.127%, 972 0.128%, 973 0.132%, 974 0.130%, 975 0.132%, 976 0.138%, 977 0.131%, 978 0.130%, 979 0.130%, 980 0.131%, 981 0.129%, 982 0.134%, 983 0.130%, 984 0.129%, 985 0.126%, 986 0.126%, 987 0.126%, 988 0.131%, 989 0.130%, 990 0.131%, 991 0.131%, 992 0.124%, 993 0.131%. Block counts divisible by 8 or more: 976 (×16), 984 (×8), 992 (×32).0.1200.1400.1600.1800.200970975980985990blocks in the filterfalse-positive rate, per cent×16×8×32reduced by a moduloreduced by its top bits128-bit blocks, four-bit thresholdsdashed: counts divisible by 8 or more
Fig. 3 The rate at 128-bit blocks against the block count, from 969 to 993 blocks. By modulo: about 0.131% where the count is odd or twice an odd number, 0.190% at 976 (a multiple of 16), 0.146% at 984 (of 8), 0.197% at 992 (of 32). From the top bits: 0.124% to 0.138% at every count.

Varying the filter by a few keys at a time, the modulo filter’s rate spikes at exactly the block counts with a large power of two in them: 0.190% at 976 blocks, 0.146% at 984 and 0.197% at 992, against about 0.131% where the count is odd or twice an odd number. The top-bit filter has no spikes. Between 969 and 993 blocks its rate stays in a band from 0.124% to 0.138%, and it wanders the way a measured rate wanders over a million queries. A filter whose rate depends on whether its block count is divisible by sixteen has a defect in it, because nothing about a block’s capacity knows its index.

The previous pages could not have seen this. Each measured one block count at each width, since the count follows from the bits a key and the width. The rate at 256 bits looked like the rate at 256 bits, with an unlucky seed. It was the rate at 504 blocks.

Why a threshold suffers and a second choice does not

The threshold design is hurt because its whole mechanism is the ordering value. Keys are placed in increasing order of that value, a tied batch at a time, and a block’s threshold closes at the first value where the block’s first-choice keys would overflow it. With independent values, a block sees keys arriving at all sixteen ordering values, about a sixteenth of its first-choice keys at each. It can close within a sixteenth of the ideal point. When the block’s index modulo 32 fixes which four of the sixteen values its keys can have, those keys arrive in four batches of a quarter each. The threshold can close only at those four points. A block that would have overflowed by one key closes a quarter of its keys out at once, and they go to second blocks chosen from the same few kinds. A four-bit threshold had become a two-bit one, with the two bits chosen differently for each residue class of blocks. The seeds then decide whether the classes’ closing points land well or badly, which is why the rate spread across seeds is a factor of 3.5.

A dependence that costs a different design nothing: at 512-bit blocks the filter has 256 blocks, and by modulo a key's two blocks take 1,024 of 65,536 possible pairs — yet the emptier-of-two filter's rate is 0.100% by modulo and 0.099% by top bits, and the one-block filter's 0.086% and 0.088%, over six seedsFalse-positive rate over six seeds, 8,192 keys at 16 bits a key and 512-bit blocks (256 blocks), both reductions. One block: modulo 0.083%, 0.089%, 0.087%, 0.089%, 0.085%, 0.082%; top bits 0.088%, 0.095%, 0.086%, 0.090%, 0.084%, 0.087%. Emptier of two: modulo 0.100%, 0.100%, 0.101%, 0.099%, 0.097%, 0.102%; top bits 0.098%, 0.097%, 0.103%, 0.102%, 0.095%, 0.098%.0.08%0.09%0.10%one blockemptier of tworeduced by a moduloreduced by its top bitseach dot: one seed256 blocks of 512 bits
Fig. 4 The emptier-of-two filter and the one-block filter at 512-bit blocks — 256 blocks, where a key’s two blocks take 1,024 of 65,536 pairs by modulo — over six seeds. Emptier of two: 0.100% by modulo, 0.099% from the top bits. One block: 0.086% and 0.088%.

The emptier-of-two filter, whose two block choices are dependent in the same way, loses nothing to it: 0.100% by modulo and 0.099% from the top bits at 256 blocks, where its pairs of blocks take 1,024 values of 65,536. Its mechanism does not use an ordering value. Each key goes to whichever of its two blocks holds fewer keys, and a kind of key, sharing its two blocks with a few others of its kind, still spreads between them. Choices that are not independent measured two choices drawn with a dependence built in on purpose and found the balance survived much of it, and this is a case of that. The one-block filter uses one hash, and one hash’s low bits are as uniform as its high ones on random keys, so it is untouched too.

So the defect is specific. It needs two values of one key, reduced by ranges that share a power of two, and a mechanism that depends on their joint distribution. The threshold filters have all three. A filter with eight-bit thresholds has them in a milder form, since its ordering value keeps eight bits and loses fewer of its levels to the dependence. On the widths the earlier pages measured, the eight-bit filter’s rate moves by at most 11% between the two reductions, in both directions, and as much at block counts that are odd, where the reduction cannot matter. That is one run’s noise, not the dependence.

What the published numbers become

What the threshold's width is worth, both ways: at 512-bit blocks a four-bit threshold costs 0.060% and an eight-bit one 0.062% with top bits (0.062% and 0.064% by modulo) — 3% apart, not the 9% a single run showed; at 256-bit blocks the modulo's four-bit filter averages 0.118% and the top bits' 0.078%False-positive rate of the one-threshold blocked filter, 8,192 keys at 16 bits a key, against the bits each threshold is stored in, averaged over four seeds, at 512- and 256-bit blocks, both reductions. 512-bit blocks: 3 bits (254 blocks) modulo 0.067% [0.064%, 0.063%, 0.072%, 0.070%], top bits 0.064% [0.063%, 0.064%, 0.064%, 0.065%]; 4 bits (254 blocks) modulo 0.062% [0.061%, 0.063%, 0.062%, 0.061%], top bits 0.060% [0.062%, 0.060%, 0.058%, 0.061%]; 5 bits (253 blocks) modulo 0.062% [0.063%, 0.061%, 0.063%, 0.063%], top bits 0.061% [0.060%, 0.062%, 0.060%, 0.060%]; 6 bits (253 blocks) modulo 0.060% [0.060%, 0.059%, 0.060%, 0.061%], top bits 0.059% [0.056%, 0.062%, 0.061%, 0.058%]; 8 bits (252 blocks) modulo 0.064% [0.063%, 0.066%, 0.064%, 0.064%], top bits 0.062% [0.062%, 0.063%, 0.061%, 0.062%]. 256-bit blocks: 3 bits (506 blocks) modulo 0.088% [0.082%, 0.085%, 0.089%, 0.096%], top bits 0.079% [0.077%, 0.082%, 0.076%, 0.081%]; 4 bits (504 blocks) modulo 0.118% [0.087%, 0.109%, 0.190%, 0.086%], top bits 0.078% [0.077%, 0.079%, 0.078%, 0.078%]; 5 bits (502 blocks) modulo 0.079% [0.080%, 0.079%, 0.077%, 0.080%], top bits 0.080% [0.078%, 0.077%, 0.083%, 0.080%]; 6 bits (500 blocks) modulo 0.081% [0.078%, 0.082%, 0.082%, 0.081%], top bits 0.080% [0.078%, 0.080%, 0.083%, 0.080%]; 8 bits (496 blocks) modulo 0.088% [0.087%, 0.088%, 0.089%, 0.086%], top bits 0.088% [0.089%, 0.086%, 0.090%, 0.087%].6e-48e-40.0010.00134568bits a threshold is stored infalse-positive rate, mean of four seeds512-bit blocks, modulo512-bit blocks, top bits256-bit blocks, modulo256-bit blocks, top bitsdashed: 256-bit blocksfour seeds, 250,000 queries a filter
Fig. 5 The one-threshold filter’s rate against the bits a threshold is stored in, mean of four seeds. At 512-bit blocks from the top bits: 0.064% at three bits, 0.060% at four, 0.061% at five, 0.059% at six, 0.062% at eight. By modulo: 0.067%, 0.062%, 0.062%, 0.060%, 0.064%. At 256-bit blocks, four bits: 0.118% by modulo and 0.078% from the top bits.

The pages this touches measured at 512-bit blocks mostly, where the block count carries one factor of two, and most of what they said survives. The claim that a threshold needs four or five bits and not eight survives in direction and shrinks in size: averaged over four seeds, a four-bit threshold beats an eight-bit one by 3% reading the top bits, and by 4% by modulo, against the 9% a single run of eight million queries reported. Three bits is still worse than four, by 6% from the top bits. Between four and eight bits the differences are within what four seeds resolve. At 256-bit blocks the modulo’s four-bit filter averages 0.118% over four seeds and the top bits’ 0.078%. Every width from three bits to six sits within 3% of that figure on the top bits.

The shared-threshold page’s ranking survives as well. Rebuilt from the top bits at 512-bit blocks, on the same million queries, one threshold a block measures 0.0605%, one shared by a pair 0.0705% and one shared by sixteen blocks 0.100%, against 0.0577%, 0.0650% and 0.0889% as published. Sharing loses at every group size either way. A run twice as long gives 0.0616%, 0.0699% and 0.0922% from the top bits and 0.0607%, 0.0730% and 0.0948% by modulo, so at 512 bits the difference between the reductions is no larger than the difference between one run and the next. The page’s centring on 512 bits turns out to have been the right instinct for the wrong reason: 512-bit blocks were steady because their block count is twice an odd number.

The two figures the earlier pages left unexplained are both explained. The 0.169% for two four-bit thresholds at 256-bit blocks was measured at 496 blocks, a multiple of sixteen. Over four seeds that design measures 0.097% to 0.176% by modulo and 0.076% to 0.080% from the top bits. The shared-threshold page’s collapse at 256 bits was the same filter at 504 blocks.

The repair and its cost

Reading a multiply-shift hash into a range means taking its top bits, which is how the family is defined: a hash into 2ℓ2^\ell buckets keeps the top ℓ\ell bits of the product. For a range that is not a power of two, the top-bit reading is ⌊h⋅r/230⌋\lfloor h \cdot r / 2^{30} \rfloor, one multiplication and one shift, and it spreads the hash’s 30 bits over the range as evenly as the modulo does. It costs no more than the modulo and on most machines less, since a division is slower than a multiplication.

What it costs here is the published numbers. The pages that built blocked filters with thresholds all measured with the modulo, and their figures and their text still agree with each other, because both were made from it. Rebuilt from the top bits, their numbers move by a few per cent at 512-bit blocks and by a third or more at 128 and 256. A penalty set by the block checked its one-block rates against Bloom’s formula averaged over a Poisson load and found them within 5%. That check passed because a one-block filter uses one hash. The threshold filters had no such check, since no formula gives their rate, and they are where the dependence was.

Why a single run could not show it

Each of the earlier pages did what a measurement here is asked to do. It built real filters, counted real false positives over millions of queries, checked that no stored key was ever denied, and compared designs on the same keys. The dependence passed all of that. A filter with a dependent ordering value is still a correct filter: it denies no stored key, and its rate is a real rate, measured honestly, for that block count. What it is not is the rate of the design the page describes, which assumes the key’s values are independent. No check on one filter’s answers can see the difference, because the answers are right.

What exposes it is a comparison the pages did not make: the same design at neighbouring sizes. A design’s rate should change smoothly with the number of blocks, since nothing about a block cares what its index is. A rate that jumps by half when the count gains a factor of two is measuring the indices. The second choice measured two hashes drawn from one seeded family and found each exactly as good as the other on its own; what the pair buys is in how the two combine. The threshold pages relied on that combination too, for an ordering value and a block rather than for two blocks, and a family that behaves for one value at a time need not behave for two values read from the same low bits.

A sweep of block counts, with a second reduction to compare against, costs one extra plate. It would have caught this where the four-bit threshold was first measured.

What this does not settle

Random keys only. Every key here is a uniformly random 32-bit integer. Keys that are themselves structured in their low bits — consecutive integers, aligned addresses — would make the modulo’s dependence worse, and would test the top-bit reading, which is only as good as the multiplier’s mixing. The independence an estimator spends caught multiply-shift failing a pairwise test decisively on keys built from its own arithmetic, and none of those probes is used here.

One hash family. The dependence is multiply-shift’s, and a family whose low output bits depend on all of the key would not have it. The fix measured here keeps the family and changes the reading, which is the smaller change.

The rebuilt numbers are single runs where the published ones were. The shared-threshold figures from the top bits are one run of two million queries, as the published ones were. The threshold widths are four seeds of two million queries each, and the ranking of three bits against four and of four against eight is resolved by them. The differences between four, five and six bits are not.

Still open: the table coded by where thresholds close, on a hash that can be trusted

The measurement the previous page proposed can now be made. On the top-bit filter, at every width, a threshold’s closing distribution is the filter’s own and not an artefact of its block count. At 512-bit blocks two blocks in five never close, and the rest close in the upper half of the ordering hash’s range, which gives the table an entropy well under its four bits. A code built from that distribution would hold the table in about two thirds of the bits.

The prediction is that the coded table matches the four-bit rate on under three bits a block, and that the question worth asking is how it is laid out. A variable-length code cannot be indexed directly. If the table is packed end to end with an index of where each chunk begins, a lookup reads the index and then the table, the second read the threshold design was built to avoid. If each cache line holds a fixed number of thresholds, a lookup finds its threshold in one line with no index. The line then has to fit its worst run of long code words, and that worst case, not the entropy, sets the table’s size. The prize is small, a third of the table at half a per cent of the filter. On a filter whose rate now holds still from one seed to the next, a saving that size is measurable, and the page that measures it will say whether a code can be read in one line.

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

Every essay whose body links to this one.

The objects this essay names

Each one links to every other essay that touches it.

Blocked filterBloom filterDesign parameterFalse-positive rateMultiply shiftThresholdTwo choicesUniversal hashing