use datasketches::bloom::BloomFilter;
use datasketches::bloom::BloomFilterBuilder;
fn published_config() -> BloomFilterBuilder {
BloomFilterBuilder::with_accuracy(CACHED_OBJECTS, 0.01)
}
const CACHED_OBJECTS: u64 = 100_000;
fn purged_objects() -> impl Iterator<Item = u64> {
(0..CACHED_OBJECTS).step_by(200)
}
fn main() {
let mut cached = published_config().build().unwrap();
for object in 0..CACHED_OBJECTS {
cached.insert(object);
}
let mut purged = published_config().build().unwrap();
for object in purged_objects() {
purged.insert(object);
}
cached.difference(&purged).unwrap();
for object in purged_objects() {
assert!(!cached.contains(&object));
}
let valid = CACHED_OBJECTS - purged_objects().count() as u64;
let mut retained = 0_u64;
for object in (0..CACHED_OBJECTS).filter(|object| object % 200 != 0) {
if cached.contains(&object) {
retained += 1;
}
}
println!("Cached objects: {CACHED_OBJECTS}");
println!("Purged objects: {}", purged_objects().count());
println!(
"Still served: {retained} / {valid} valid objects ({:.1}% retained; drops become cache misses)",
retained as f64 / valid as f64 * 100.0
);
assert!(retained as f64 >= valid as f64 * 0.9);
let bytes = cached.serialize();
let shipped = BloomFilter::deserialize(&bytes).unwrap();
assert_eq!(shipped, cached);
println!("Shipped filter: {} bytes", bytes.len());
}