Hazy
A dependency-free Python toolkit for fast, mergeable probabilistic data structures, implemented in Rust.
Start with the problem
If you know the engineering constraint but not the sketch parameters, Hazy can choose them:
from hazy import plan
recommendation = plan(
"count_unique",
expected_items=100_000_000,
error_rate=0.01,
max_memory="16 MiB",
)
counter = recommendation.create()
print(recommendation.explain())
plan() turns a goal, error target, and memory budget into a configured data
structure. You can still construct every structure directly when you want
full control.
Why Hazy?
When working with massive datasets, exact answers become expensive. Counting unique visitors across billions of events? A precise solution needs gigabytes of memory. Checking if a URL exists in a blocklist of millions? Exact lookups are slow.
Probabilistic data structures solve this by trading perfect accuracy for dramatic improvements in speed and memory. A HyperLogLog can count 1 billion unique items using just 16KB of memory (with ~1% error). A Bloom filter can check membership in a set of 10 million items using 12MB instead of hundreds of megabytes.
Hazy provides compact implementations with one consistent Python API, batch operations, deterministic hashing, and a Rust core. Use it when you need to:
- Count unique items in streams too large to fit in memory
- Check set membership without storing every element
- Estimate frequencies of items in high-throughput streams
- Find similar documents without comparing every pair
- Track top-K items in real-time leaderboards
Features
- Bloom Filter: Space-efficient set membership testing
- Counting Bloom Filter: Bloom filter with deletion support
- Scalable Bloom Filter: Auto-scaling Bloom filter for unknown cardinality
- Cuckoo Filter: Fixed-capacity membership filter with deletion
- HyperLogLog: Cardinality estimation with ~2% error using minimal memory
- Count-Min Sketch: Frequency estimation for streaming data
- MinHash: Set similarity estimation using Jaccard index
- Top-K (Space-Saving): Find the most frequent items in a stream
Engineering features
- Rust backend with GIL-free batch operations
- xxHash3 for fast, high-quality hashing
- Pre-hashed input for interoperable high-throughput pipelines
- Goal-oriented planning from accuracy and memory requirements
- Byte and JSON serialization for storage and transport
- File I/O with save()/load() for persistence
Installation
pip install hazy
Building from source
Requires a current stable Rust toolchain and Python 3.9+:
# Install Rust if needed
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Build and install
pip install maturin
maturin develop --release
Quick Start
from hazy import BloomFilter, HyperLogLog, CountMinSketch
# Bloom Filter - set membership
bf = BloomFilter(expected_items=10000, false_positive_rate=0.01)
bf.add("hello")
print("hello" in bf) # True
print("world" in bf) # False (probably)
# HyperLogLog - count unique items
hll = HyperLogLog(precision=14)
hll.update_many(f"user_{i}" for i in range(1_000_000))
print(f"Unique users: {hll.cardinality():.0f}") # ~1,000,000
# Count-Min Sketch - frequency estimation
cms = CountMinSketch(width=10000, depth=5)
cms.add("apple")
cms.add("apple")
cms.add("banana")
print(f"Apple count: {cms['apple']}") # >= 2
Example: unique users from an event stream
This processes one million events without building a set of user IDs:
from hazy import plan
recommendation = plan(
"count_unique",
expected_items=50_000_000,
error_rate=0.01,
max_memory="16 MiB",
)
counter = recommendation.create()
events = ({"user_id": f"user-{i % 250_000}"} for i in range(1_000_000))
for event in events:
counter.add(event["user_id"])
print(f"Estimated unique users: {counter.cardinality():,.0f}")
print(f"Sketch memory: {counter.size_in_bytes / 1024:,.0f} KiB")
The runnable version is in examples/unique_users.py.
Direct parameter selection
Use the estimation helpers to choose optimal parameters:
from hazy import estimate_bloom_params, estimate_hll_params
# Bloom filter for 1M items at 1% FPR
params = estimate_bloom_params(expected_items=1_000_000, false_positive_rate=0.01)
print(f"Memory needed: {params.memory_mb:.1f} MB")
print(f"Hash functions: {params.num_hashes}")
# HyperLogLog for 1% error
params = estimate_hll_params(expected_cardinality=1_000_000, error_rate=0.01)
print(f"Precision: {params.precision}")
print(f"Memory: {params.memory_bytes} bytes")
API Overview
All structures share a consistent API:
# Add items
structure.add(item) # Add single item
structure.update(items) # Add multiple items
structure.update_many(items) # Explicit optimized batch path
# Query
structure.query(item) # Query (meaning varies by structure)
structure.query_many(items) # Batch query where applicable
item in structure # Membership test (where applicable)
# Combine
structure.merge(other) # Combine two structures
result = structure | other # Union operator (where applicable)
# Serialize
data = structure.to_bytes() # Binary serialization
structure = Type.from_bytes(data)
json_str = structure.to_json()
structure = Type.from_json(json_str)
# Introspection
len(structure) # Approximate count
structure.size_in_bytes # Memory footprint
# File I/O
structure.save("filter.hazy")
structure = Type.load("filter.hazy")
Data Structures
BloomFilter
from hazy import BloomFilter
bf = BloomFilter(expected_items=10000)
bf.add("hello")
assert "hello" in bf
assert bf.false_positive_rate < 0.02
CountingBloomFilter
from hazy import CountingBloomFilter
cbf = CountingBloomFilter(expected_items=10000)
cbf.add("hello")
cbf.add("hello")
cbf.remove("hello") # Still contains "hello"
cbf.remove("hello") # Now removed
Only remove items known to have been inserted. Like other probabilistic filters, a positive membership check can be a false positive; removing an item that was never added can decrement counters shared with real items.
ScalableBloomFilter
from hazy import ScalableBloomFilter
# Automatically grows as you add items
sbf = ScalableBloomFilter(initial_capacity=1000)
for i in range(1_000_000): # Way more than initial capacity
sbf.add(f"item_{i}")
print(f"Slices: {sbf.num_slices}") # Multiple slices created
print("item_500" in sbf) # True
CuckooFilter
from hazy import CuckooFilter
cf = CuckooFilter(capacity=10000)
cf.add("hello")
cf.remove("hello")
assert "hello" not in cf
For the same reason, only remove keys known to have been inserted: an absent key can share a fingerprint with a stored key.
HyperLogLog
from hazy import HyperLogLog
hll = HyperLogLog(precision=14) # 16KB memory, ~0.8% error
hll.update([f"item_{i}" for i in range(1000000)])
print(f"Cardinality: {hll.cardinality():.0f}")
CountMinSketch
from hazy import CountMinSketch
cms = CountMinSketch(width=10000, depth=5)
# Or: cms = CountMinSketch(error_rate=0.001, confidence=0.99)
cms.add("apple", count=10)
print(f"Apple frequency: {cms['apple']}")
MinHash
from hazy import MinHash
mh1 = MinHash(num_hashes=128)
mh1.update(["a", "b", "c", "d"])
mh2 = MinHash(num_hashes=128)
mh2.update(["c", "d", "e", "f"])
print(f"Jaccard similarity: {mh1.jaccard(mh2):.2f}") # ~0.33
TopK
from hazy import TopK
tk = TopK(k=10)
for word in ["apple"] * 100 + ["banana"] * 50 + ["cherry"] * 25:
tk.add(word)
for item, count in tk.top(3):
print(f"{item}: {count}")
Visualization
Install with visualization support:
pip install hazy[viz]
Plotting
from hazy import BloomFilter, HyperLogLog, CountMinSketch, TopK
from hazy.viz import plot_bloom, plot_hll, plot_cms, plot_topk, show
# Bloom filter bit array heatmap
bf = BloomFilter(expected_items=10000)
bf.update([f"item_{i}" for i in range(5000)])
plot_bloom(bf)
# HyperLogLog register histogram
hll = HyperLogLog(precision=12)
hll.update([f"user_{i}" for i in range(100000)])
plot_hll(hll)
# Count-Min Sketch heatmap
cms = CountMinSketch(width=100, depth=5)
for word in ["apple"] * 50 + ["banana"] * 30 + ["cherry"] * 10:
cms.add(word)
plot_cms(cms)
# Top-K bar chart
tk = TopK(k=10)
tk.update(["apple"] * 100 + ["banana"] * 50 + ["cherry"] * 25)
plot_topk(tk)
show() # Display all figures
Jupyter Notebooks
Enable rich HTML display in Jupyter:
import hazy
hazy.enable_notebook_display()
bf = hazy.BloomFilter(expected_items=1000)
bf.add("hello")
bf # Displays rich HTML with stats and progress bar
Development
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Build release wheel
maturin build --release
Reproducible comparisons with pyprobables, datasketch, pybloom-live, and
zpds are in benchmarks/.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hazy-0.3.1.tar.gz.
File metadata
- Download URL: hazy-0.3.1.tar.gz
- Upload date:
- Size: 141.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
de92d93cb16bd4cf755db65c70286f475ceed7a75635dabb97f9a0d0847d9182
|
|
| MD5 |
a2b9f0fcffdc50c2a8d20ea7db361035
|
|
| BLAKE2b-256 |
799379dc692f2f7534e3ccc84865447fa5730f9d0dec496fe3d0acf364ea5b89
|
Provenance
The following attestation bundles were made for hazy-0.3.1.tar.gz:
Publisher:
release.yml on carolinehaoud/hazy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hazy-0.3.1.tar.gz -
Subject digest:
de92d93cb16bd4cf755db65c70286f475ceed7a75635dabb97f9a0d0847d9182 - Sigstore transparency entry: 2419522005
- Sigstore integration time:
-
Permalink:
carolinehaoud/hazy@2a9937b9cd41df3526ecf85e064441acae6c3951 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/carolinehaoud
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2a9937b9cd41df3526ecf85e064441acae6c3951 -
Trigger Event:
push
-
Statement type:
File details
Details for the file hazy-0.3.1-cp39-abi3-win_amd64.whl.
File metadata
- Download URL: hazy-0.3.1-cp39-abi3-win_amd64.whl
- Upload date:
- Size: 398.6 kB
- Tags: CPython 3.9+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
26ffa042f49974f0be9161599bd28253d33fda3beee8cd8f2e3540415295a9c8
|
|
| MD5 |
a5c7ce0a39d13e4af3a785236d4f0ed7
|
|
| BLAKE2b-256 |
4579b4882d1877c8a27bb7d9c17be14f6da3725517bb011a512fc06802ef26d1
|
Provenance
The following attestation bundles were made for hazy-0.3.1-cp39-abi3-win_amd64.whl:
Publisher:
release.yml on carolinehaoud/hazy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hazy-0.3.1-cp39-abi3-win_amd64.whl -
Subject digest:
26ffa042f49974f0be9161599bd28253d33fda3beee8cd8f2e3540415295a9c8 - Sigstore transparency entry: 2419525428
- Sigstore integration time:
-
Permalink:
carolinehaoud/hazy@2a9937b9cd41df3526ecf85e064441acae6c3951 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/carolinehaoud
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2a9937b9cd41df3526ecf85e064441acae6c3951 -
Trigger Event:
push
-
Statement type:
File details
Details for the file hazy-0.3.1-cp39-abi3-musllinux_1_2_x86_64.whl.
File metadata
- Download URL: hazy-0.3.1-cp39-abi3-musllinux_1_2_x86_64.whl
- Upload date:
- Size: 718.8 kB
- Tags: CPython 3.9+, musllinux: musl 1.2+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0f4b284af25c3586e46b4a94171abb1f1aadcca468aaf5cf817e1cb159457aa7
|
|
| MD5 |
99311fa751c81fceec36d190f67f27fe
|
|
| BLAKE2b-256 |
dd0f1108c1ecdb1b06f3641f26d038e0d1ae515653f383f9f6fdbb9351a96818
|
Provenance
The following attestation bundles were made for hazy-0.3.1-cp39-abi3-musllinux_1_2_x86_64.whl:
Publisher:
release.yml on carolinehaoud/hazy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hazy-0.3.1-cp39-abi3-musllinux_1_2_x86_64.whl -
Subject digest:
0f4b284af25c3586e46b4a94171abb1f1aadcca468aaf5cf817e1cb159457aa7 - Sigstore transparency entry: 2419523203
- Sigstore integration time:
-
Permalink:
carolinehaoud/hazy@2a9937b9cd41df3526ecf85e064441acae6c3951 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/carolinehaoud
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2a9937b9cd41df3526ecf85e064441acae6c3951 -
Trigger Event:
push
-
Statement type:
File details
Details for the file hazy-0.3.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: hazy-0.3.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 505.7 kB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0f88134dfa77719c12d2ac290066773de8947ba30b2c8557c2d9de09286536b1
|
|
| MD5 |
b81710f290189f157d3d526abe169e96
|
|
| BLAKE2b-256 |
82f427f5bd53628dd9b31196571c41684870b2eb69ee726874d3420f1ea9d3a6
|
Provenance
The following attestation bundles were made for hazy-0.3.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release.yml on carolinehaoud/hazy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hazy-0.3.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
0f88134dfa77719c12d2ac290066773de8947ba30b2c8557c2d9de09286536b1 - Sigstore transparency entry: 2419527108
- Sigstore integration time:
-
Permalink:
carolinehaoud/hazy@2a9937b9cd41df3526ecf85e064441acae6c3951 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/carolinehaoud
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2a9937b9cd41df3526ecf85e064441acae6c3951 -
Trigger Event:
push
-
Statement type:
File details
Details for the file hazy-0.3.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: hazy-0.3.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 495.7 kB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
287d1d09dec6a8c73212162a460476c396acd2ec4c3eeb749bc402d31439a139
|
|
| MD5 |
7902b0faa14c51f7a9e7ed062a4ce2c1
|
|
| BLAKE2b-256 |
9a44900d7211f0c9ed27f543b68184c4e2fb20c7681ae5074c267a7bfe4b2275
|
Provenance
The following attestation bundles were made for hazy-0.3.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
release.yml on carolinehaoud/hazy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hazy-0.3.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
287d1d09dec6a8c73212162a460476c396acd2ec4c3eeb749bc402d31439a139 - Sigstore transparency entry: 2419524444
- Sigstore integration time:
-
Permalink:
carolinehaoud/hazy@2a9937b9cd41df3526ecf85e064441acae6c3951 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/carolinehaoud
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2a9937b9cd41df3526ecf85e064441acae6c3951 -
Trigger Event:
push
-
Statement type:
File details
Details for the file hazy-0.3.1-cp39-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: hazy-0.3.1-cp39-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 463.5 kB
- Tags: CPython 3.9+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6a16df69f7978ae5f35257a0cf0e084cdef97b1263ee7b0d114a9cc8fcaf2308
|
|
| MD5 |
608357cce00fe57b90249af4fe58b041
|
|
| BLAKE2b-256 |
84b7229aa9e459369b8e41b4104578a560362bef24f86f55405dd973dfa8f840
|
Provenance
The following attestation bundles were made for hazy-0.3.1-cp39-abi3-macosx_11_0_arm64.whl:
Publisher:
release.yml on carolinehaoud/hazy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hazy-0.3.1-cp39-abi3-macosx_11_0_arm64.whl -
Subject digest:
6a16df69f7978ae5f35257a0cf0e084cdef97b1263ee7b0d114a9cc8fcaf2308 - Sigstore transparency entry: 2419526280
- Sigstore integration time:
-
Permalink:
carolinehaoud/hazy@2a9937b9cd41df3526ecf85e064441acae6c3951 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/carolinehaoud
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2a9937b9cd41df3526ecf85e064441acae6c3951 -
Trigger Event:
push
-
Statement type:
File details
Details for the file hazy-0.3.1-cp39-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: hazy-0.3.1-cp39-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 480.7 kB
- Tags: CPython 3.9+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4d71b7ed01c7856bcf76cfb903cb76c066b43682246b786d3e11a6b40f983f86
|
|
| MD5 |
653385c08a6b55110410f422ab010b84
|
|
| BLAKE2b-256 |
6956fd97d61f271fdb93c36a32a994908ec83d1c1d578dc8c96d00b353fef288
|
Provenance
The following attestation bundles were made for hazy-0.3.1-cp39-abi3-macosx_10_12_x86_64.whl:
Publisher:
release.yml on carolinehaoud/hazy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hazy-0.3.1-cp39-abi3-macosx_10_12_x86_64.whl -
Subject digest:
4d71b7ed01c7856bcf76cfb903cb76c066b43682246b786d3e11a6b40f983f86 - Sigstore transparency entry: 2419523675
- Sigstore integration time:
-
Permalink:
carolinehaoud/hazy@2a9937b9cd41df3526ecf85e064441acae6c3951 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/carolinehaoud
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2a9937b9cd41df3526ecf85e064441acae6c3951 -
Trigger Event:
push
-
Statement type: