use std::{
sync::Arc,
time::{Duration, Instant},
};
use criterion::{criterion_group, criterion_main, Bencher, Criterion};
use data_encoding::BASE64;
use rand::{
prelude::{SliceRandom, ThreadRng},
thread_rng, RngCore,
};
use rusqlite::Connection;
use sqlite_cache::{Cache, CacheConfig};
fn gen_pairs(rng: &mut ThreadRng, size: usize) -> Vec<(String, Vec<u8>)> {
(0..size)
.map(|_| {
let mut k = vec![0u8; (rng.next_u64() % 100 + 32) as usize];
let mut v = vec![0u8; (rng.next_u64() % 1000) as usize];
rng.fill_bytes(&mut k);
rng.fill_bytes(&mut v);
(BASE64.encode(&k), v)
})
.collect::<Vec<_>>()
}
fn bench_get_mt(b: &mut Bencher, size: usize, num_threads: usize) {
let mut rng = thread_rng();
let cache = Cache::new(
CacheConfig::default(),
Connection::open_in_memory().unwrap(),
)
.unwrap();
let topic = cache.topic("test").unwrap();
let pairs = gen_pairs(&mut rng, size);
for (k, v) in &pairs {
topic.set(k, v, Duration::from_secs(3600)).unwrap();
}
let pairs = Arc::new(pairs);
b.iter_custom(|n| {
let start = Instant::now();
let handles = (0..num_threads)
.map(|_| {
let pairs = pairs.clone();
let topic = topic.clone();
std::thread::spawn(move || {
let mut rng = thread_rng();
for _ in 0..n {
let (k, v) = pairs.choose(&mut rng).unwrap();
let got_value = topic.get(k).unwrap().unwrap();
assert_eq!(&got_value.data, v);
}
})
})
.collect::<Vec<_>>();
for h in handles {
h.join().unwrap();
}
start.elapsed()
});
}
fn bench_get(b: &mut Bencher, size: usize) {
bench_get_mt(b, size, 1)
}
fn bench_set_mt(b: &mut Bencher, size: usize, num_threads: usize) {
let mut rng = thread_rng();
let cache = Cache::new(
CacheConfig::default(),
Connection::open_in_memory().unwrap(),
)
.unwrap();
let topic = cache.topic("test").unwrap();
let pairs = gen_pairs(&mut rng, size);
let pairs = Arc::new(pairs);
b.iter_custom(|n| {
let start = Instant::now();
let handles = (0..num_threads)
.map(|_| {
let pairs = pairs.clone();
let topic = topic.clone();
std::thread::spawn(move || {
let mut rng = thread_rng();
for _ in 0..n {
let (k, v) = pairs.choose(&mut rng).unwrap();
topic.set(k, v, Duration::from_secs(3600)).unwrap();
}
})
})
.collect::<Vec<_>>();
for h in handles {
h.join().unwrap();
}
start.elapsed()
});
}
fn bench_set(b: &mut Bencher, size: usize) {
bench_set_mt(b, size, 1)
}
fn criterion_benchmark(c: &mut Criterion) {
c.bench_function("lookup - cache size 10000", |b| bench_get(b, 10000));
c.bench_function("lookup mt(4) - cache size 10000", |b| {
bench_get_mt(b, 10000, 4)
});
c.bench_function("insert - cache size 10000", |b| bench_set(b, 10000));
c.bench_function("insert mt(4) - cache size 10000", |b| {
bench_set_mt(b, 10000, 4)
});
}
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);