Advanced 26 min readModule: Module 16: Probabilistic Streaming Algorithms: HyperLogLog & Sketches
Probabilistic Algorithms: HyperLogLog & Count-Min Sketch
Process massive streaming big data in fixed memory with Probabilistic Algorithms: HyperLogLog (counting 1 billion unique users in 1.5KB RAM), Count-Min Sketch for frequency estimation, and Cuckoo Filters for dynamic item deletion.
What You Will Learn in This Lesson
- The trade-off of Probabilistic Data Structures: trading 1% precision for a 99.9% memory reduction
- How HyperLogLog (HLL) estimates unique cardinality by observing maximum leading zeros in hash values
- Harmonic Mean and register bucket bias correction in the Flajolet-Martin algorithm
- Count-Min Sketch: estimating event frequencies in high-throughput network packet streams
Introduction & Core Concept
Counting the exact number of unique visitors (cardinality) across 1,000,000,000 requests using a HashSet requires ~16GB of RAM. The HyperLogLog (HLL) algorithm accomplishes this with a typical error rate of ~1% while consuming only 1.5 Kilobytes of memory. By observing the distribution of leading zeros in uniform cryptographic hash values across multiple register buckets, HLL computes accurate cardinality estimates in constant O(1) space.
WHY DOES THIS MATTER IN THE REAL WORLD?
Redis (`PFADD`, `PFCOUNT`), Google BigQuery (`APPROX_COUNT_DISTINCT`), and Cloudflare analytics track billions of unique daily users in real time using HyperLogLog.
Syntax & Structure
javascript
// Redis CLI HyperLogLogPFADD visitors "user_101" "user_102"PFCOUNT visitors // Estimated cardinality in 1.5KB RAMSimulating HyperLogLog Cardinality Estimation with Bucket Registers
javascriptjavascript
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162// HyperLogLog (HLL) Cardinality Estimator Simulationclass SimpleHyperLogLog {constructor(b = 6) {this.b = b; // 2^b registers (e.g. 2^6 = 64 bucket registers)this.m = 1 << b;this.registers = new Uint8Array(this.m);// Alpha constant for 64 bucketsthis.alpha = 0.709;}// 32-bit Integer Hash Function (Murmur-like bit mixer)_hash(str) {let h = 2166136261 >>> 0;for (let i = 0; i < str.length; i++) {h ^= str.charCodeAt(i);h = Math.imul(h, 16777619) >>> 0;}return h;}// Count leading zeros after bucket index_clz(val) {if (val === 0) return 32 - this.b;return Math.clz32(val);}add(item) {const hash = this._hash(item);// Extract bucket register index from first 'b' bitsconst bucketIndex = hash >>> (32 - this.b);// Extract remaining hash bitsconst remainingBits = (hash << this.b) >>> 0;const leadingZeros = this._clz(remainingBits) + 1;// Keep maximum observed leading zeros in bucket registerif (leadingZeros > this.registers[bucketIndex]) {this.registers[bucketIndex] = leadingZeros;}}count() {// Compute Harmonic Mean of registers to reduce outlier variancelet sum = 0;for (let i = 0; i < this.m; i++) {sum += Math.pow(2, -this.registers[i]);}const rawEstimate = (this.alpha * this.m * this.m) / sum;return Math.round(rawEstimate);}}const hll = new SimpleHyperLogLog(6); // 64 registers// Add 500 unique simulated itemsfor (let i = 1; i <= 500; i++) {hll.add("user_account_id_" + i);}console.log("=== Probabilistic HyperLogLog Cardinality Engine ===");console.log("Actual Unique Elements Inserted: 500");console.log("HyperLogLog Estimated Count: ", hll.count());console.log("Total Memory Consumed by HLL: ", hll.registers.length, "bytes (Tiny 64-byte footprint!)");console.log("✅ Estimated 500 unique items within standard HLL error bounds!");
Line-by-Line Technical Breakdown
1Count-Min Sketch: While HLL counts unique cardinality, Count-Min Sketch estimates frequency (how many times did item X appear in the stream?). It uses D independent hash functions to increment counters across a 2D matrix, returning the minimum counter value for queries with zero false negatives.
Try It Yourself (Interactive Editor)
Modify the code in real-time and click Run to test live browser output and console logs.
Intelligent Code Runner & Live Sandbox[JAVASCRIPT]
JAVASCRIPT SOURCE EDITOR
Interactive Live CodeCommon Mistakes & How to Avoid Them
#1: Using HyperLogLog when exact 100% precision is legally or mathematically required (e.g. financial bank balance calculations).
HyperLogLog is an approximation algorithm. It is ideal for metrics and analytics, but should not be used where exact precision is required.
Incorrect / Antipattern
// Using HLL for exact billing invoicesCorrect / Professional Solution
// Use exact database COUNT(DISTINCT) for financial billing; use HLL for analytics dashboardsIndustry Best Practices & Professional Standards
- Use Redis `PFADD` / `PFCOUNT` for tracking unique daily active users (DAU) across millions of visitors.
- Use Count-Min Sketch for tracking top-K heavy hitters and rate limiting in network firewalls.
- Use Cuckoo Filters instead of Bloom Filters if your system requires deleting items dynamically.
Lesson Summary & Core Takeaways
- Probabilistic data structures trade minimal precision for 99.9% memory savings.
- HyperLogLog estimates unique cardinality across billions of items in 1.5KB RAM.
- Count-Min Sketch and Bloom Filters provide constant-space frequency and membership testing.