Generator

Probes per insertion against load factor, table of 8,192

Rendered here at the parameters it defaults to, with every essay that calls it — which is the same list as the blast radius of changing it.
Probes per insertion against load factor, table of 8,192The line is Knuth's closed form for linear probing, integrated over the fill; the points are a table actually filled and counted. They agree to within 2.3% everywhere. At a load factor of 0.5 an insertion averages 1.49 probes; at 0.9 it averages 5.39. The formula that matters for insertion is the unsuccessful-search one, ½(1 + 1/(1−α)²), and using the successful-search form instead is an error that hides at low load and is glaring at high load.1234560.000.250.500.75formulameasuredload factor αprobes per insertion8,192 slots, mean of 8 fills, seeds stated in lib/structures.jstwo routes agree to 2.3%

Probes per insertion against load factor, table of 8,192

The line is Knuth's closed form for linear probing, integrated over the fill; the points are a table actually filled and counted. They agree to within 2.3% everywhere. At a load factor of 0.5 an insertion averages 1.49 probes; at 0.9 it averages 5.39. The formula that matters for insertion is the unsuccessful-search one, ½(1 + 1/(1−α)²), and using the successful-search form instead is an error that hides at low load and is glaring at high load.

Drawn at 670 × 400, wide on the page. Everything above is what probe-count returns with no arguments; the caption is the generator's own, computed from the numbers in the drawing rather than written beside it.

21 essays call probe-count. The drawing above is what it returns with no arguments at all; every call below passes it something, because a placement that passes nothing draws whichever member of the family the generator happens to default to rather than the one its essay argues about — which is what optcheck and figfill exist to catch.

Where it is called

Changing this generator changes every one of these figures.

-50%-40%-30%-20%-10%0%10%20%2561,0244,09616,384α = 0.5α = 0.8α = 0.9α = 0.95table size (slots)measured minus formula, relativemean of 6 fills per pointgreen band: within 5% of the formula What a bound is

A limit is not a prediction

1234560.000.250.500.75formulameasuredload factor αprobes per insertion8,192 slots, mean of 8 fills, seeds stated in lib/structures.jstwo routes agree to 2.3% What is taught wrongly

The probe formula nobody checks

46810120.010.1bits per element (m / n)false-positive ratemeasured(1 − e^(−kn/m))^kfrom the bits set60,000 absent-key queries per point, seed 80800 false negatives at every size When the algorithm flips a coin

A filter that is allowed to be wrong

average 8.001,0242,048bucket, 0 to 255keys in the bucketthe low bits · keys built for this hashworst bucket 2,048 against 8.0 When the algorithm flips a coin

A hash is a family, not a function

04812162024283236404448slots from homepale: linear probing · dark: Robin Hoodmean 2.384identical for bothworst 48 → 12var 37 → 7435 keys, 512 slots, seed 20260811displacements, counted exactly Structures

The probe nobody waits for

48163264128110entry width, bytescache lines a lookup readsentries inlinea line of tags in front8,192 slots, load 0.9, buckets of 8keys the table holds What the machine does

A lookup that stops caring how wide an entry is

linear probingchainedcuckoo, two tables0240.10.20.30.40.50.60.70.80.9load factorentries read per lookup0120.10.20.30.40.50.60.70.80.9load factorcache misses per lookup8,192 slots, 64 cache lines of 8a probe is an entry read; a miss is a line fetched What the machine does

Two probes are two misses

linear probingcuckoo, two tablescuckoo, buckets of 8024680.30.450.60.750.850.95load factorentries read per lookup00.511.50.30.450.60.750.850.95load factorcache misses per lookup8,192 slots, 64 cache lines of 8a probe is an entry read; a miss is a line fetched What the machine does

The bucket that fits a line

a second hash, unordered0.054 entries read on an absent key14.435.79 storedthe bits below the bucket, unordered0.059 entries read on an absent key14.435.79 storedthe bits below the bucket, sorted0.057 entries read on an absent key8.975.21 storedthe bucket's own bits, sorted5.743 entries read on an absent key11.275.80 storedtag comparisons an absent key's lookup makes8,192 slots · buckets of 8 · 8-bit tags38% fewer What the machine does

A tag that answers more than yes

501001500.2000.4000.6000.800load: keys held ÷ slotsbytes held per keythe entry, 32 bytesslotted entriespacked, a pointer a bucketpacked, groups of 4 bucketspacked, groups of 1616,384 slots, buckets of 8, 32-byte entrieslabels at the lowest load What the machine does

Entries found by the rank of their tag

1248163210010³spare entries a group of 16 buckets keepsbytes moved an insertionslack at the endslack spread, region rewrittenslack spread, nearest gapborrowedslotsload 0.5, groups of 16dashed: the slotted layout What the machine does

The slack an insertion can reach

05001e+31.5e+3load when the insertion is madebytes moved an insertion50%70%90%95%spare divided evenlyspare by recent insertionsspare by room leftfixed slots16 spare a region of sixteen bucketsdashed: fixed slots What the machine does

Spare where a bucket can use it

05001e+31.5e+3load when the insertion is madebytes moved an insertion50%70%90%95%no capcap 2, overflow in the sparecap 2, overflow in a blocksixteen spare a region, divided by room leftcharged since the previous tenth What the machine does

The keys a capped chain leaves behind

filter bits for each overflow keyfailed lookups that reach a block0246810120%25%50%75%100%at 95% loadat 90% loadone filter16,384 absent keys, cap of twodashed: one Bloom filter at those bits What the machine does

The lookups a filter turns away

00.0200.0400.0600.0800.10002468operations, in multiples of the table's 16,384 entriesshare of keys in overflowkeys stay, 9.2%home at every deletion, 4.0%home when open, 4.9%16,384 entries, buckets of eight, cap of two95% load What the machine does

The block already open

0%2%4%6%8%10%12%share of keys outside their buckets9.2%r = 0room 95.0%9.2%r = 1room 95.7%9.2%r = 2room 96.5%9.0%r = 4room 98.1%9.3%r = 8room 101.3%11.0%r = 16room 108.6%lower: in an overflow block · upper: in the region's reservekeys stay, 95% load What the machine does

Room the chains could not reach

234buckets read per insertionshare of keys in overflow, settled0.01%0.1%1%10%cap 2cap 4cap 8cap 16cap 32blind kicksone-level looktwo-level look16,384 entries · buckets of eight · 95% loadoverflow, log scale What the machine does

A kick that looks before it moves

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 What the machine does

A look that spreads the room

246lookups for every insertion (log scale)bucket reads an operation0.10.3131030100blind kicks, cap of 2blind kicks, cap of 32look, first with room, cap 2look, the emptiest, cap 2two-level look95% load, stored keys asked for evenlycheapest: blind2, first2 What the machine does

Overflow holds the old keys

blind kicks, cap of 21.0841.420blind kicks, oldest moved, cap of 21.0401.331look, first with room, cap 21.0821.361look, the oldest with room, cap 21.0641.309look, the oldest with room, oldest kicked, cap 21.0531.288two-level look1.0861.379upper bar: by recency · lower: evenly · from one read95% load, after churnreads a lookup What the machine does

A kick that moves the oldest

00.2000.4000.600residents drawn, the oldest of them kicked (8: the bucket's oldest)kicks whose key found room12348cap of 2cap of 8cap of 3295% load, after churnshare of kicks What the machine does

An old key is a crowded key

The library, page 3 of 5 — where probe-count sits