use super::utils::{append_random, init, Ordinal, ITEMS_PER_BLOB};
use commonware_runtime::{
benchmarks::{context, tokio},
tokio::Config,
Runner,
};
use commonware_storage::utils::bits_for_indices;
use commonware_utils::{TestRng, NZU64};
use criterion::{criterion_group, Criterion};
use futures::{stream::FuturesUnordered, StreamExt};
use rand::RngExt as _;
use std::{hint::black_box, time::Instant};
const ITEMS: u64 = 250_000;
pub fn select_indices(count: usize, items: u64) -> Vec<u64> {
let mut rng = TestRng::new(42);
let mut selected_indices = Vec::with_capacity(count);
for _ in 0..count {
selected_indices.push(rng.random_range(0..items));
}
selected_indices
}
pub async fn read_serial_indices(store: &Ordinal, indices: &[u64]) {
for idx in indices {
black_box(store.get(*idx).await.unwrap().unwrap());
}
}
pub async fn read_concurrent_indices(store: &Ordinal, indices: &[u64]) {
let mut futures = FuturesUnordered::new();
for idx in indices {
futures.push(store.get(*idx));
}
while let Some(result) = futures.next().await {
black_box(result.unwrap().unwrap());
}
}
fn bench_get(c: &mut Criterion) {
let cfg = Config::default();
let builder = commonware_runtime::tokio::Runner::new(cfg.clone());
let bits = builder.start(|ctx| async move {
let mut store = init(ctx, None).await;
let indices = append_random(&mut store, ITEMS).await;
store.sync().await.unwrap();
bits_for_indices(NZU64!(ITEMS_PER_BLOB), indices)
});
let runner = tokio::Runner::new(cfg.clone());
for mode in ["serial", "concurrent"] {
for reads in [1_000, 10_000, 50_000] {
let label = format!("{}/mode={} reads={}", module_path!(), mode, reads);
c.bench_function(&label, |b| {
b.to_async(&runner).iter_custom({
let bits = bits.clone();
move |iters| {
let bits = bits.clone();
async move {
let ctx = context::get::<commonware_runtime::tokio::Context>();
let bits = bits
.iter()
.map(|(section, bitmap)| (*section, bitmap))
.collect();
let store = init(ctx, Some(bits)).await;
let selected_indices = select_indices(reads, ITEMS);
let start = Instant::now();
for _ in 0..iters {
match mode {
"serial" => {
read_serial_indices(&store, &selected_indices).await
}
"concurrent" => {
read_concurrent_indices(&store, &selected_indices).await
}
_ => unreachable!(),
}
}
start.elapsed()
}
}
});
});
}
}
let cleaner = commonware_runtime::tokio::Runner::new(cfg);
cleaner.start(|ctx| async move {
let store = init(ctx, None).await;
store.destroy().await.unwrap();
});
}
criterion_group! {
name = benches;
config = Criterion::default().sample_size(10);
targets = bench_get
}