use criterion::{black_box, criterion_group, criterion_main, Criterion};
use oxcache::Cache;
fn bench_l1_operations(c: &mut Criterion) {
let rt = tokio::runtime::Runtime::new().unwrap();
let cache = rt.block_on(async { Cache::builder().build().await.unwrap() });
rt.block_on(async {
for i in 0..1000 {
let key = format!("bench_key_{}", i);
let value = format!("bench_value_{}", i);
let _ = cache.set(&key, &value).await;
}
});
c.bench_function("l1_get_hit", |b| {
b.to_async(&rt).iter(|| async {
let _: Option<String> = cache.get(black_box(&"bench_key_42".to_string())).await.unwrap();
});
});
c.bench_function("l1_get_miss", |b| {
b.to_async(&rt).iter(|| async {
let _: Option<String> = cache.get(black_box(&"nonexistent_key".to_string())).await.unwrap();
});
});
c.bench_function("l1_set", |b| {
b.to_async(&rt).iter(|| async {
let key = format!("set_key_{}", std::time::SystemTime::now().elapsed().unwrap().as_nanos());
let value = "test_value".to_string();
let _ = cache.set(black_box(&key), black_box(&value)).await;
});
});
c.bench_function("l1_get_or_set", |b| {
b.to_async(&rt).iter(|| async {
let key = format!(
"get_or_set_key_{}",
std::time::SystemTime::now().elapsed().unwrap().as_nanos()
);
let value: String = cache
.get_or(&key, || async {
Ok(format!(
"computed_value_{}",
std::time::SystemTime::now().elapsed().unwrap().as_nanos()
))
})
.await
.unwrap();
black_box(value);
});
});
}
fn bench_l1_sizes(c: &mut Criterion) {
let rt = tokio::runtime::Runtime::new().unwrap();
let cache = rt.block_on(async { Cache::builder().build().await.unwrap() });
let mut group = c.benchmark_group("l1_different_sizes");
for &size in [10, 100, 1000, 10000].iter() {
#[allow(clippy::needless_borrows_for_generic_args)]
group.bench_with_input(&format!("size_{}", size), &size, |b, size| {
b.to_async(&rt).iter(|| async {
let key = format!("size_test_{}", size);
let value = vec![0u8; *size];
let _ = cache.set(&key, &value).await;
});
});
}
group.finish();
}
fn bench_l1_sequential(c: &mut Criterion) {
let rt = tokio::runtime::Runtime::new().unwrap();
let cache = rt.block_on(async { Cache::builder().build().await.unwrap() });
let mut group = c.benchmark_group("l1_sequential");
for &ops in [10, 50, 100].iter() {
#[allow(clippy::needless_borrows_for_generic_args)]
group.bench_with_input(&format!("ops_{}", ops), &ops, |b, ops| {
b.to_async(&rt).iter(|| async {
for i in 0..*ops {
let key = format!("seq_key_{}", i);
let value = format!("seq_value_{}", i);
let _ = cache.set(&key, &value).await;
let _result: Result<Option<String>, _> = cache.get(&key).await;
}
});
});
}
group.finish();
}
fn bench_throughput(c: &mut Criterion) {
let rt = tokio::runtime::Runtime::new().unwrap();
let cache = rt.block_on(async { Cache::builder().build().await.unwrap() });
let mut group = c.benchmark_group("throughput");
for &ops_count in [100, 500, 1000, 5000].iter() {
#[allow(clippy::needless_borrows_for_generic_args)]
group.bench_with_input(&format!("ops_{}", ops_count), &ops_count, |b, ops_count| {
b.to_async(&rt).iter(|| async {
for i in 0..*ops_count {
let key = format!("throughput_key_{}", i);
let value = format!("throughput_value_{}", i);
let _ = cache.set(&key, &value).await;
}
});
});
}
group.finish();
}
criterion_group!(
benches,
bench_l1_operations,
bench_l1_sizes,
bench_l1_sequential,
bench_throughput
);
criterion_main!(benches);