use criterion::{criterion_group, criterion_main, Criterion};
use maxminddb::geoip2;
use maxminddb::{LookupResult, PathElement, Reader};
use std::hint::black_box;
use std::net::IpAddr;
mod common;
use common::{generate_ipv4, open_reader};
const DB_FILE: &str = "GeoLite2-City.mmdb";
fn cache_lookups<'a, T>(ips: &[IpAddr], reader: &'a Reader<T>) -> Vec<LookupResult<'a, T>>
where
T: AsRef<[u8]>,
{
ips.iter()
.map(|ip| reader.lookup(*ip).unwrap())
.filter(|r| r.has_data())
.collect()
}
fn bench_lookup_only<T>(ips: &[IpAddr], reader: &Reader<T>)
where
T: AsRef<[u8]>,
{
for ip in ips {
let result = reader.lookup(*ip).unwrap();
black_box(result.has_data());
}
}
fn bench_decode_city_only<T>(results: &[LookupResult<'_, T>])
where
T: AsRef<[u8]>,
{
for result in results {
let city: Option<geoip2::City<'_>> = result.decode().unwrap();
black_box(city);
}
}
fn bench_decode_country_only<T>(results: &[LookupResult<'_, T>])
where
T: AsRef<[u8]>,
{
for result in results {
let country: Option<geoip2::Country<'_>> = result.decode().unwrap();
black_box(country);
}
}
fn bench_decode_path_country_iso<T>(results: &[LookupResult<'_, T>])
where
T: AsRef<[u8]>,
{
let path = [PathElement::Key("country"), PathElement::Key("iso_code")];
for result in results {
let value: Option<&str> = result.decode_path(&path).unwrap();
black_box(value);
}
}
fn bench_decode_path_city_name<T>(results: &[LookupResult<'_, T>])
where
T: AsRef<[u8]>,
{
let path = [
PathElement::Key("city"),
PathElement::Key("names"),
PathElement::Key("en"),
];
for result in results {
let value: Option<&str> = result.decode_path(&path).unwrap();
black_box(value);
}
}
pub fn serde_usage_benchmark(c: &mut Criterion) {
let ips = generate_ipv4(100);
let reader = open_reader(DB_FILE);
let cached_results = cache_lookups(&ips, &reader);
c.bench_function("serde_usage/lookup_only", |b| {
b.iter(|| bench_lookup_only(&ips, &reader))
});
c.bench_function("serde_usage/decode_city_only", |b| {
b.iter(|| bench_decode_city_only(&cached_results))
});
c.bench_function("serde_usage/decode_country_only", |b| {
b.iter(|| bench_decode_country_only(&cached_results))
});
c.bench_function("serde_usage/decode_path_country_iso", |b| {
b.iter(|| bench_decode_path_country_iso(&cached_results))
});
c.bench_function("serde_usage/decode_path_city_name", |b| {
b.iter(|| bench_decode_path_city_name(&cached_results))
});
}
criterion_group! {
name = benches;
config = Criterion::default().sample_size(20);
targets = serde_usage_benchmark
}
criterion_main!(benches);