What the machine does

A look that spreads the room

A cuckoo table's insertion that meets a full bucket can look at its residents' other buckets before moving anyone, and the look that stops at the first with room leaves 0.20% of keys in overflow at 95% load. Moving the resident to the emptiest of the eight instead was predicted to leave none, for one and a half more reads, by spreading the table's free slots rather than consuming them where they are found. It leaves 0.08% for 2.8 more reads, and at 97% load it barely helps. The room does spread, and spread room is still room a look cannot reach: one more level of looking, at fewer reads, leaves none.

A kick that looks before it moves changed how a cuckoo table makes room. The table holds 16,384 entries in buckets of eight laid out on one cache line, and each key may live in either of two buckets chosen by two hashes. An insertion that finds its first bucket full used to kick a random resident to that resident’s other bucket, and kick again from there, up to a cap of two kicks, after which the key was filed in an overflow block. The look reads the other bucket of each of the full bucket’s residents in turn and moves the first one whose other bucket has room, so the new key takes its slot without a chain. At 95% load, under the same cap of two, the look left 0.20% of keys in overflow after churn, where blind kicks had left 9.2%.

Its closing section noticed that the look’s choice was arbitrary. Stopping at the first resident with room fills that resident’s other bucket, which might have had one free slot or three. A look that read all eight residents’ other buckets before choosing could move the resident to the emptiest, and would leave the table’s free slots spread over more buckets instead of consuming them where they happened to be found. It predicted that this look would read about one and a half more buckets an insertion than the first-found look, since the first with room is usually the third or fourth resident, and that it would hold overflow at nought where the first-found look leaves 0.20% at 95% load and 0.89% at 97%, because buckets with exactly one free slot would become rarer. It named the way it could fail: a table at 95% load has one free slot for every twenty entries, and moving keys toward empty buckets might only shuffle where the full buckets are without making any fewer of them.

The look spreads the room, and the failure it named is close to what happens. It also turns out to be the wrong place to spend the reads.

Reading all eight and choosing

Everything except the choice is the earlier essay’s: the table, the hashes, the cap of two, eight rounds of churn after the fill (a random deletion and a fresh insertion each), keys the cap stops filed in the overflow block of their first bucket’s region of sixteen buckets, and the count of bucket reads, in which a bucket inside the region already read is free. The emptiest-bucket look reads the other bucket of every resident of the full bucket, notes how many free slots each has, and moves the resident whose other bucket has the most, the first such in reading order when several tie. If none has room, the insertion falls back to the blind kick under the cap, as before. The first-found look is unchanged, and so are blind kicks at caps from two to sixty-four and the two-level look, which, when no resident’s other bucket has room, looks at the other buckets of those buckets’ residents.

The table is run at 90%, 95%, 97% and 98% load. Every design’s churn checks that the keys in buckets and in overflow add up to the keys stored and that every key sits in one of its two buckets.

Less overflow, at the price of more reads

At 95% load, moving the resident to the emptiest of its eight other buckets leaves 0.08% of keys in overflow for 7.12 bucket reads an insertion, against 0.20% for 4.34 when the look stops at the first with room; looking a level deeper instead leaves 0.00% for 4.31The share of keys in overflow after eight rounds of churn at 95% load against the buckets read per insertion. Blind kicks: cap 2 9.20% at 1.63, cap 3 6.94% at 1.87, cap 4 5.60% at 2.10, cap 6 3.76% at 2.48, cap 8 2.62% at 2.80, cap 12 1.43% at 3.34, cap 16 0.68% at 3.72, cap 24 0.14% at 4.14, cap 32 0.02% at 4.23, cap 64 0.00% at 4.23. One-level look stopping at the first bucket with room: cap 0 2.87% at 2.88, cap 1 0.76% at 3.86, cap 2 0.20% at 4.34, cap 4 0.00% at 4.41. One-level look moving to the emptiest: cap 0 2.03% at 5.66, cap 1 0.44% at 6.78, cap 2 0.08% at 7.12, cap 4 0.00% at 7.15. Two-level look: first with room 0.00% at 4.31, the emptiest 0.00% at 6.78. A share of nought is drawn at 0.001%; points past 14 reads are left off the plate.246buckets read per insertionshare of keys in overflow, settled0.001%0.01%0.1%1%10%blind kicks, caps 2 to 64look, first with roomlook, the emptiesttwo levels (large dots)caps 0, 1, 2, 4 on the looks95% load, 16,384 entriesoverflow on a log scale
Fig. 1 At 95% load, overflow after churn against bucket reads an insertion. Blind kicks: 9.20% at 1.63 reads (cap 2), 0.68% at 3.72 (16), 0.02% at 4.23 (32). The look stopping at the first with room: 2.87% at 2.88 (cap 0), 0.20% at 4.34 (cap 2), nought at 4.41 (cap 4). The look moving to the emptiest: 2.03% at 5.66, 0.08% at 7.12 (cap 2), nought at 7.15 (cap 4). The two-level look: nought at 4.31.

At 95% load, under the cap of two, the emptiest-bucket look leaves 0.08% of keys in overflow, against 0.20% for the look that stops at the first with room, and reads 7.12 buckets an insertion against 4.34. The prediction said nought, for about one and a half more reads. The overflow falls by three fifths and the reads rise by 2.8.

On the plate the two looks are two curves of the same shape, the emptiest one shifted right by nearly three reads. At every cap the emptiest look has less overflow; at every level of overflow the first-found look reaches it with fewer reads. Under a cap of four both leave nothing, 4.41 reads against 7.15. The cap of two that the earlier essay compared at is the only place where the choice of resident matters, because it is the only place where the look’s misses still reach overflow often enough to count.

The design that wins the plate is neither. The two-level look, which searches the residents of the residents’ other buckets when the first level finds nothing, leaves no key in overflow at 95% load for 4.31 reads an insertion, fewer than the first-found look and 2.8 fewer than the emptiest.

Where the extra reads come from

A look that stops at the first resident with room stops, on average, at resident 3.3 of eight at 95% load and finds none in 14% of its looks; the emptiest-bucket look reads all eight and finds room in 90% of its looks against 86%, 79% against 78% at 97%For the one-level look that stops at the first resident whose other bucket has room, under a cap of two: the share of its looks that stop at each of the eight residents, and the share that find no room, at 95% and 97% load. 95%: 1 21%, 2 17%, 3 14%, 4 11%, 5 9%, 6 7%, 7 5%, 8 3%, none 14%, mean 3.33; looks finding room, first 86%, emptiest 90%. 97%: 1 16%, 2 14%, 3 12%, 4 10%, 5 9%, 6 7%, 7 6%, 8 4%, none 22%, mean 3.61; looks finding room, first 78%, emptiest 79%.00.0500.1000.1500.2000.25012345678the resident whose other bucket had room, in reading ordershare of looks95% load97% loadno room: 14% and 22%one-level look, first with roomshare of looks
Fig. 2 For the look that stops at the first resident with room, under a cap of two: the share of its looks that stop at each of the eight residents. At 95% load 21% stop at the first resident, 17% at the second, 14% at the third, and 14% of looks find no room, a mean of resident 3.3 among those that find it. At 97%, 22% find no room. The emptiest-bucket look finds room in 90% of its looks at 95% and 79% at 97%, against 86% and 78%.

The look that stops at the first resident with room stops, on average, at the 3.3rd resident of eight at 95% load, so the emptiest-bucket look, which always reads all eight, reads about four more buckets each time it looks. The prediction’s arithmetic had the right position and the wrong subtraction. It took the first with room to be the third or fourth, which it is, and counted one and a half extra reads. But a look that stops early reads fewer than four buckets on average, counting the looks that find nothing and read all eight, so reading all eight every time costs about four more; and looking runs at every full bucket a chain meets, which at this load is seven insertions in ten. An insertion that finds its first bucket full reads 9.96 buckets under the emptiest-bucket look against 5.69 under the first-found look.

What the extra reads buy is visible in the same plate. The emptiest-bucket look finds room in 90% of its looks at 95% load, against 86% for the first-found look, because the buckets it leaves behind are less often completely full. Four looks in a hundred that would have gone on to a blind kick, and sometimes to overflow, now succeed. That is a real effect of spreading the room, and it is small.

Spread room is still scarce room

The emptiest-bucket rule spreads the room rather than keeping it: after churn at 95% load 24% of buckets have exactly one free slot under it, against 21% when the look takes the first with room, and 7% have two to four against 8%; full buckets fall only from 71% to 69%The share of the table's 2,048 buckets of eight holding no free slot, one, two, three, and four or more, after eight rounds of churn at 95% load, under each design. one-level look, first with room: 0 free 71%, 1 free 21%, 2 free 6%, 3 free 2%, 4+ free 1%; overflow 0.20%. one-level look, the emptiest: 0 free 69%, 1 free 24%, 2 free 5%, 3 free 1%, 4+ free 0%; overflow 0.08%. two-level look, first with room: 0 free 71%, 1 free 20%, 2 free 6%, 3 free 2%, 4+ free 1%; overflow 0.00%. blind kicks, cap of 32: 0 free 71%, 1 free 21%, 2 free 6%, 3 free 2%, 4+ free 0%; overflow 0.02%.0 free1 free2 free3 free4+ free0%25%50%75%100%one-level look, first with roomone-level look, the emptiesttwo-level look, first with roomblind kicks, cap of 3295% load, after churnshare of buckets
Fig. 3 After churn at 95% load, the share of buckets with no free slot, one, two, three, and four or more. The first-with-room look: 71%, 21%, 6%, 2%, 1%. The emptiest: 69%, 24%, 5%, 1%, under 1%. The two-level look and blind kicks under a cap of 32 look like the first: 71% and 20 to 21% with one free slot.

After churn at 95% load, the emptiest-bucket rule leaves 24% of buckets with exactly one free slot, against 21% under the first-found look, and 7% with two or more against 8%; full buckets fall only from 71% to 69%. The prediction said that buckets with one free slot would become rarer. They become commoner, which is what spreading room means at this load. A table at 95% load has 819 free slots among 2,048 buckets, two fifths of a slot a bucket. Moving keys toward the buckets with the most room takes slots from the buckets that had three and gives them to buckets that had none, so the distribution narrows: fewer buckets with several free slots, a few more with one, and slightly fewer with none.

The closing section named this risk precisely: at a given load the room is a fixed quantity, and a placement rule can only rearrange it. The packed table met the same arithmetic when it divided a region’s spare among its buckets: room put where it can be used helps, and no division makes more of it. The rearrangement helps because a look succeeds when any one of eight other buckets has a slot, and having the slots on more buckets raises that chance a little: from 86% to 90%. It does not help much, because 69% of the buckets a look reads are still full. At 95% load the room is scarce whatever shape it takes.

The other two designs on the plate leave the room in nearly the same shape as the first-found look. Neither of them chooses where to put a key, and both reach far less overflow than the rule that does. The difference between designs is not in the shape of the room they leave but in how far they search for it.

A base and an exponent

The two ways of spending reads act on different parts of one number. A one-level look fails when all eight of the residents’ other buckets are full. If buckets were full independently, with a chance pp each, that would happen with chance p8p^8. Spreading the room acts on pp: the emptiest-bucket rule lowers the share of full buckets from 71% to 69%, which takes p8p^8 from 6.5% to 5.1%, a fall of a fifth. Looking a level deeper acts on the exponent: the second level reads the other buckets of up to fifty-six more residents, and p64p^{64} is under one in ten million at either value of pp.

The measured failure rates are higher than the independent ones, 14% for the first-found look and 10% for the emptiest, because full buckets are not independent; the likeliest reason, not separately measured, is that a full bucket’s residents tend to have full other buckets too, so a look that starts in a crowded part of the table stays there. But the direction is the arithmetic’s. A rule that changes the base by two points cannot compete with one that multiplies the exponent by eight, and the plates show the second leaving nothing in overflow at 95% load for fewer reads than the first spends to leave 0.08%.

Where room is scarcest, spreading helps least

At 97% load, moving the resident to the emptiest of its eight other buckets leaves 0.72% of keys in overflow for 8.72 bucket reads an insertion, against 0.89% for 5.65 when the look stops at the first with room; looking a level deeper instead leaves 0.01% for 7.03The share of keys in overflow after eight rounds of churn at 97% load against the buckets read per insertion. Blind kicks: cap 2 10.23% at 1.66, cap 3 8.01% at 1.93, cap 4 6.69% at 2.18, cap 6 4.99% at 2.64, cap 8 3.81% at 3.06, cap 12 2.49% at 3.76, cap 16 1.70% at 4.46, cap 24 0.85% at 5.47, cap 32 0.43% at 6.26, cap 64 0.02% at 7.17. One-level look stopping at the first bucket with room: cap 0 4.00% at 3.07, cap 1 1.77% at 4.54, cap 2 0.89% at 5.65, cap 4 0.17% at 6.99. One-level look moving to the emptiest: cap 0 3.32% at 5.94, cap 1 1.48% at 7.62, cap 2 0.72% at 8.72, cap 4 0.16% at 10.03. Two-level look: first with room 0.01% at 7.03, the emptiest 0.00% at 9.10. A share of nought is drawn at 0.001%; points past 14 reads are left off the plate.246810buckets read per insertionshare of keys in overflow, settled0.001%0.01%0.1%1%10%blind kicks, caps 2 to 64look, first with roomlook, the emptiesttwo levels (large dots)caps 0, 1, 2, 4 on the looks97% load, 16,384 entriesoverflow on a log scale
Fig. 4 At 97% load. Blind kicks: 1.70% at 4.46 reads (cap 16), 0.43% at 6.26 (32), 0.02% at 7.17 (64). The first-with-room look: 0.89% at 5.65 (cap 2), 0.17% at 6.99 (cap 4). The emptiest: 0.72% at 8.72 (cap 2), 0.16% at 10.03 (cap 4). The two-level look: 0.010% at 7.03.

At 97% load the emptiest-bucket look leaves 0.72% of keys in overflow under the cap of two, against the first-found look’s 0.89%, for 8.72 reads an insertion against 5.65. The prediction’s nought is two orders of magnitude away. With three free slots for every hundred entries, a look’s eight other buckets are all full more than a fifth of the time, and spreading the slots over more buckets cannot change that much when there are so few slots to spread. Under a cap of four the two looks are level, 0.16% and 0.17% of keys in overflow, and the emptiest pays three more reads for it.

The two-level look leaves 0.010% at 7.03 reads, and blind kicks under a cap of sixty-four leave 0.02% at 7.17. Both search further for less than the emptiest-bucket look spends searching wider.

Spreading the room helps least where room is scarcest: the emptiest-bucket look cuts the first-with-room look's overflow from 0.20% to 0.08% at 95% load and only from 1.50% to 1.32% at 98%, where a two-level look leaves 0.10%The share of keys in overflow after churn at loads of 90%, 95%, 97%, 98%, for each design, with its bucket reads an insertion. one-level look, first with room: 90% 0.00% at 2.43 reads, 95% 0.20% at 4.34 reads, 97% 0.89% at 5.65 reads, 98% 1.50% at 6.29 reads. one-level look, the emptiest: 90% 0.00% at 4.64 reads, 95% 0.08% at 7.12 reads, 97% 0.72% at 8.72 reads, 98% 1.32% at 9.46 reads. two-level look, first with room: 90% 0.00% at 2.37 reads, 95% 0.00% at 4.31 reads, 97% 0.01% at 7.03 reads, 98% 0.10% at 10.14 reads. blind kicks, cap of 32: 90% 0.00% at 2.29 reads, 95% 0.02% at 4.23 reads, 97% 0.43% at 6.26 reads, 98% 0.92% at 7.19 reads. A share of nought is drawn at 0.001%.loadshare of keys in overflow, settled90%95%97%98%0.001%0.01%0.1%1%one-level look, first with roomone-level look, the emptiesttwo-level look, first with roomblind kicks, cap of 32after eight rounds of churnoverflow on a log scale
Fig. 5 Overflow after churn at each load. The first-with-room look: nought at 90%, 0.20% at 95%, 0.89% at 97%, 1.50% at 98%. The emptiest: nought, 0.08%, 0.72%, 1.32%. The two-level look: nought, nought, 0.010%, 0.10%. Blind kicks under a cap of 32: nought, 0.02%, 0.43%, 0.92%.

From 95% load to 98% the emptiest-bucket look’s advantage over the first-found look shrinks from a factor of two and a half to a factor of 1.14: 0.08% against 0.20%, then 1.32% against 1.50%. At 98% the two-level look leaves 0.10% and blind kicks under a cap of 32 leave 0.92%. Every design’s overflow rises with load, and the ordering of the four does not change at any load above 90%, where all of them leave nothing. A placement rule acts on how room is arranged, and the closer a table comes to full the less arrangement there is to act on.

What an insertion pays

At 95% load the emptiest-bucket look reads 2.79 more buckets an insertion than the look that stops at the first with room, not the predicted one and a half, and an insertion that meets a full bucket reads 9.96 under it against 5.69: it reads all eight where the other stops at about the thirdThe mean buckets read by an insertion whose first bucket is full, including that bucket, at each load, for each design. one-level look, first with room: 90% 3.67, 95% 5.69, 97% 7.05, 98% 7.69. one-level look, the emptiest: 90% 9.01, 95% 9.96, 97% 11.15, 98% 11.74. two-level look, first with room: 90% 3.60, 95% 5.62, 97% 8.42, 98% 11.61. blind kicks, cap of 32: 90% 3.47, 95% 5.51, 97% 7.60, 98% 8.58.0510loadbucket reads, insertions meeting a full first bucket90%95%97%98%one-level look, first with roomone-level look, the emptiesttwo-level look, first with roomblind kicks, cap of 32after eight rounds of churnthe first bucket counted
Fig. 6 Bucket reads for an insertion whose first bucket is full, at each load. The first-with-room look: 3.67 at 90%, 5.69 at 95%, 7.05 at 97%, 7.69 at 98%. The emptiest: 9.01, 9.96, 11.15, 11.74. The two-level look: 3.60, 5.62, 8.42, 11.61. Blind kicks under a cap of 32: 3.47, 5.51, 7.60, 8.58.

An insertion that meets a full first bucket reads 9.96 buckets under the emptiest-bucket look at 95% load, against 5.62 under the two-level look, which leaves nothing in overflow, and 5.69 under the first-found look. The emptiest-bucket look’s price is nearly fixed, nine to twelve reads at every load, and every one of those reads is a cache line, the unit the machine actually charges, because it reads all eight residents’ buckets at every full bucket it meets whatever their state. The two-level look’s price rises steeply with load, from 3.60 to 11.61, because it reads the second level only when the first finds nothing, and at 98% that is most of the time. Below 98% the two-level look is the cheaper of the two at every load, and at 98% they cost nearly the same while the two-level look leaves a thirteenth as much in overflow.

That makes the comparison the earlier essay drew sharper. The first-found look reads a bucket and stops if it has room, which is the cheapest possible use of a read. The two-level look continues that, one level further, only when the first level has failed. The emptiest-bucket look spends its extra reads on buckets that are no use for this insertion, reading all eight to choose among the ones with room, in order to make the next insertion slightly likelier to find room. Room the chains could not reach found that a table at 95% load stands 13.8% empty after churn while keys sit in overflow; the room is there, and what a design buys with its reads is reach to it, not a better arrangement of it.

What the prediction got right

The closing section predicted that the emptiest-bucket look would read about one and a half more buckets an insertion than the first-found look, and hold overflow at nought where the first-found look leaves 0.20% at 95% load and 0.89% at 97%. It reads 2.8 more, because it reads all eight residents’ buckets at every full bucket a chain meets, and leaves 0.08% and 0.72%. It predicted that buckets with exactly one free slot would become rarer, and they become commoner, from 21% to 24%, because spreading a fixed amount of room over more buckets is exactly that.

It named the failure as the shape of the free room being fixed by the load, so that every placement rule meets the same full buckets in a different order. The shape is not quite fixed: the rule moves about 2% of buckets from no free slot to one and 1% from several to one, and its looks succeed four times more in a hundred. But the load fixes how much room there is, and at 95% that is two fifths of a slot a bucket. A look can make the table a little easier for the insertions after it. The cheaper way to help them is to look further for this one.

What the table assumes

One way to choose. The emptiest bucket, ties to the first read. A look could weigh the room it finds against the reads already spent, or prefer an emptier bucket only when it is in the region already read and free; neither was run.

Reads as the only price. A bucket read is one unit whether it is a cache line the insertion was going to touch or one it was not. The emptiest-bucket look writes slightly less than the first-found look, 1.76 entries an insertion against 1.82 at 95%, since its moves land where they are less often undone, but writes are not what any of these designs is short of.

One seed of churn a design. Every number is one table churned for eight rounds, and the overflow shares at 95% load are a few dozen keys. The orderings between designs are the same at every load from 95% to 98%, which is the evidence that they are not noise.

Still open: the price of a key left in overflow

Every design here was judged on two numbers, the overflow it leaves and the reads an insertion pays, and the plates leave the exchange rate between them open. A key in overflow is not free to keep: every lookup of it reads its two buckets, finds nothing, and reads the overflow block as well, so its cost is paid every time it is asked for. A table that is read ten times for every write should pay many reads at insertion to keep a key out of overflow; one that is written as often as it is read should not.

The measurement that follows charges each design for both: the reads its insertions pay, plus, for every lookup, the extra read a key in overflow costs, at mixes from one lookup for every insertion to a hundred, with lookups drawn uniformly over the stored keys and again in proportion to a skewed popularity. It then finds, at each load and mix, the design and cap that cost least in total. The prediction is that at one lookup an insertion the plain first-found look under a cap of two is cheapest at 95% load, since its 0.20% of overflow costs a fifth of a read for every hundred lookups, and that by ten lookups an insertion the two-level look is cheapest at every load from 95% up. It could fail on skew. If the keys that end up in overflow are the ones inserted most recently, and recent keys are the ones looked up most, overflow costs far more than its share suggests, and the deep search pays at mixes where a uniform count says it does not. The question is whether a table’s search depth should be set by its load alone or by how often what it stores is asked for.

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.

Cuckoo hashingDesign parameterHash tableLoad factorMeasured countWorst case