Cuckoo Filter
A cuckoo filter is a dynamic probabilistic set-membership data structure introduced by Bin Fan, Dave G. Andersen, Michael Kaminsky, and Michael D. Mitzenmacher in 2014 that uses partial-key cuckoo hashing over 4-slot buckets to support worst-case O(1) lookups and deletions at 95% table occupancy.
Cuckoo Filter is a compact, dynamic probabilistic data structure in computation and algorithms that tests approximate set membership with zero false negatives, worst-case O(1) lookup and deletion latency, and lower space overhead than a standard Bloom filter for false-positive rates ฮต < 3%. Introduced by Bin Fan, Dave G. Andersen, Michael Kaminsky, and Michael D. Mitzenmacher at ACM CoNEXT 2014, a cuckoo filter stores short f-bit fingerprints of inserted keys inside a bucketized cuckoo hashing table rather than setting bits in a flat bit array.
In computational complexity theory and high-throughput networking systems, classical Bloom filters prohibit element deletion (because clearing any bit B[hi(x)] could create false negatives for other stored keys sharing that bit) and require k = โ0.693 (m/n)โ independent memory accesses per lookup. Counting Bloom filters support deletions only by inflating every bit into a 3- or 4-bit counter (3ร to 4ร memory overhead). By introducing partial-key cuckoo hashingโan involutory bitwise XOR relocation scheme that computes a fingerprint's alternate bucket address without retaining the original keyโa cuckoo filter with 4-slot buckets achieves 95.5% table occupancy, executes every lookup and deletion in at most two CPU cache-line reads, and supports Semi-Sorting bucket compression that saves an additional 1 bit per item.
Partial-Key Cuckoo Hashing and Bucketized Table Architecture
Why Standard Cuckoo Eviction Fails Without Full Keys
In standard cuckoo hashing (Pagh & Rodler, 2001), each key x is assigned two independent bucket locations i1 = h1(x) and i2 = h2(x) in an array of m buckets. When inserting a new key x into a full bucket i1, the table evicts an existing occupant y from bucket i1 and relocates y to its alternate bucket by recomputing h1(y) and h2(y) from the stored full key y.
In a compact approximate-membership filter, however, the full key y is discarded upon insertion; each slot stores only a short f-bit fingerprint ฯ = fingerprint(y) โ {1, ..., 2f โ 1} (typically f = 8, 12, or 16 bits, reserving the all-zero value 0 for empty slots). Because the original key y is no longer available during an eviction, evaluating an independent hash function h2(y) is impossible.
The Involutory XOR Identity of Partial-Key Cuckoo Hashing
Fan, Andersen, Kaminsky, and Mitzenmacher solved this relocation problem by defining the second candidate bucket index i2 as the bitwise exclusive-OR (โ) of the first bucket index i1 and the hash of the f-bit fingerprint ฯ = fingerprint(x), where the number of buckets m = 2q is a power of two:
Because bitwise XOR is self-inverse (a โ b โ b = a), the relationship between i1 and i2 is fully symmetric:
Consequently, whenever an incumbent fingerprint ฯ sitting in any current bucket i โ {i1, i2} is evicted during an insertion, its twin candidate bucket j is computed directly from i and ฯ aloneโwithout knowing the original key x or even whether i was originally i1 or i2:
Notably, hashing the fingerprint via h2(ฯ) (rather than XORing the raw f-bit integer ฯ directly into i1) is essential: if ฯ were XORed without hashing when 2f โช m, the alternate bucket i2 would always lie within ยฑ2f slots of i1, causing pronounced localized clustering and premature insertion failure. Applying an invertible mixing hash h2(ฯ) distributes alternate buckets across the entire m-bucket table.
Core Operations: Insertion, Lookup, and Safe Deletion
Bucketized (d = 2, b = 4) Layout and Lookup
A canonical cuckoo filter consists of an array T[0 .. m โ 1] of m buckets, where each bucket holds b = 4 fingerprint slots of f bits each. To test whether a query key x is in the set (Lookup(x)):
- Compute the f-bit non-zero fingerprint ฯ = fingerprint(x), the primary bucket i1 = h1(x), and the alternate bucket i2 = i1 โ h2(ฯ).
- Read the 4 slots of bucket T[i1] and the 4 slots of bucket T[i2] (which can be compared against ฯ in a single SIMD instruction). If any of the 2b = 8 slots contains ฯ, return true; otherwise return false.
Eviction Insertion and Safe Deletion
- Insertion (Insert(x)): Compute ฯ, i1, and i2. If either bucket T[i1] or T[i2] has a vacant slot, store ฯ in that slot and return. Otherwise, pick i โ {i1, i2} at random and enter the cuckoo eviction loop (for up to MaxNumKicks = 500 iterations): randomly select one of the b = 4 fingerprints ฯโฒ in T[i], swap ฯ โ ฯโฒ, update i โ i โ h2(ฯ), and return as soon as T[i] has a free slot.
- Deletion (Delete(x)): Compute ฯ, i1, and i2. If either bucket T[i1] or T[i2] contains a matching copy of ฯ, clear one matching copy to 0 and return true. (As in any deletion-capable filter, only keys known to have been previously inserted may be deleted so as not to remove another member key that collided on both bucket and fingerprint; if identical keys are inserted multiple times, up to 2b = 8 duplicate copies can be stored across the two buckets.)
False-Positive Rate, Load Factor, and Space-Optimality Analysis
Fingerprint Length f as a Function of False-Positive Rate ฮต and Bucket Size b
When querying a non-member key y โ S, the query inspects 2b slots across the two candidate buckets T[i1] and T[i2]. A false positive occurs if any of the occupied slots in those two buckets holds the same f-bit fingerprint ฯ = fingerprint(y). Because each stored fingerprint matches ฯ independently with probability 1 / 2f, the probability of a false positive across at most 2b comparisons is bounded by:
Solving for the required fingerprint bit width f yields:
Dividing by the maximum load factor ฮฑ of a (d = 2, b)-slot cuckoo table gives the amortized space cost C in bits per stored item:
| Bucket Capacity b (Slots/Bucket) | Maximum Load Factor ฮฑ | Extra Bits per Fingerprint (1 + log2 b) | Bits per Item C at ฮต = 1% | Bits per Item C at ฮต = 0.1% | Semi-Sorted Bits per Item at ฮต = 0.1% |
|---|---|---|---|---|---|
| b = 1 (Standard 2-Choice) | 50.0% (0.500) | +1 bit | 15.29 bits | 21.93 bits | โ |
| b = 2 Slots/Bucket | 84.0% (0.840) | +2 bits | 10.29 bits | 14.25 bits | 13.06 bits |
| b = 4 Slots/Bucket (Canonical) | 95.5% (0.955) | +3 bits | 10.10 bits | 13.58 bits | 12.53 bits |
| b = 8 Slots/Bucket | 98.0% (0.980) | +4 bits | 10.86 bits | 14.25 bits | 13.23 bits |
| Standard Bloom Filter | โ (p0 = 0.50) | ร 1.4427 factor | 9.58 bits | 14.38 bits | โ (No deletions) |
Because a Bloom filter scales multiplicatively as 1.4427 log2(1/ฮต) bits per item whereas a (b = 4) cuckoo filter scales additively as (log2(1/ฮต) + 3) / 0.955 bits per item, cuckoo filters use less memory than Bloom filters whenever ฮต < 3% (and under Semi-Sorting compressionโwhich sorts the 4 fingerprints inside each bucket and encodes their high-order bits via a 12-bit permutation index, saving 1 bit per itemโwhenever ฮต < 2%).
Semi-Sorting Compression and Theoretical Refinements
In a 4-slot bucket (b = 4), the order of the 4 fingerprints within the bucket carries no semantic meaning. By sorting the four f-bit fingerprints in each bucket and grouping their 4 most significant bits into one of the (16 + 4 โ 1 choose 4) = 3,876 monotonic 4-tuplesโwhich fits inside a 12-bit table index instead of 4 ร 4 = 16 bitsโSemi-Sorting saves 4 bits per bucket (1 bit per item), lowering the cost to (log2(1/ฮต) + 2) / 0.955 bits per item.
From a theoretical perspective,David Eppstein (2016) proved that because partial-key cuckoo hashing restricts the alternate bucket difference i1 โ i2 to the 2f values of h2(ฯ), high-probability insertion ensures hold rigorously when the fingerprint width satisfies f = ฮฉ((log n) / b). When b = 4 and f โฅ 8 bits, empirical and asymptotic analyses confirm 95.5% occupancy across multi-billion-key tables in network routers, consistent hashing directory caches, and distributed database storage engines alongside the quotient filter and Xor filter.
Frequently Asked Questions
What happens if more than 2b = 8 keys collide on both the primary bucket i1 and the f-bit fingerprint ฯ?
Because two keys with the same primary bucket i1 and the same fingerprint ฯ also share the precise same alternate bucket i2 = i1 โ h2(ฯ), at most 2b (8 for b = 4) such identical-fingerprint keys can fit into buckets i1 and i2 combined. To keep the probability of > 2b identical (i1, ฯ) collisions negligible across n keys, the total number of distinct (i1, ฯ) pairs m ยท 2f must outscale n, which requires f = ฮฉ((log n) / b) bits (typically f โฅ 8 bits for b = 4).
Why can a Cuckoo Filter not use f = 0 or omit fingerprints altogether?
Even if false positives did not matter, partial-key cuckoo hashing requires storing a non-zero fingerprint ฯ in each slot so that an evicted item can compute its alternate bucket i2 = i1 โ h2(ฯ), and it reserves the value ฯ = 0 to mark unoccupied slots (re-mapping any key whose hash produces 0 to ฯ = 1).
References
- Fan, B., Andersen, D. G., Kaminsky, M., & Mitzenmacher, M. D. (2014). "Cuckoo Filter: Practically better than Bloom." Proceedings of the 10th ACM International on Conference on Emerging Networking Experiments and Technologies (CoNEXT '14), 75โ88. https://doi.org/10.1145/2674005.2674994
- Pagh, R., & Rodler, F. F. (2004). "Cuckoo hashing." Journal of Algorithms, 51(2), 122โ144. https://doi.org/10.1016/j.jalgor.2003.12.002
- Dietzfelbinger, M., & Weidling, C. (2007). "Balanced allocation and dictionaries with tightly packed constant size bins." Theoretical Computer Science, 380(1โ2), 47โ68. https://doi.org/10.1016/j.tcs.2007.02.054
- Eppstein, D. (2016). "Cuckoo filter: Simplification and analysis." Proceedings of the 15th Scandinavian Symposium and Workshops on Algorithm Theory (SWAT 2016), LIPIcs Vol. 53, 8:1โ8:12. https://doi.org/10.4230/LIPIcs.SWAT.2016.8
- Breslow, A. D., Zhang, D. P., Greathouse, J. L., Jayasena, N., & Tullsen, D. M. (2016). "Horton tables: Fast hash tables for in-memory data-intensive computing." Proceedings of the 2016 USENIX Annual Technical Conference (USENIX ATC '16), 281โ294. https://doi.org/10.5555/3026959.3026986