use crate::{get_fixed_journal, get_variable_journal};
use commonware_runtime::{
Supervisor as _,
benchmarks::{context, tokio},
};
use commonware_storage::journal::contiguous::Mutable;
use commonware_utils::{NZU64, sequence::FixedBytes};
use criterion::{Criterion, criterion_group};
use std::{
num::NonZeroU64,
time::{Duration, Instant},
};
const PARTITION: &str = "append-sync-partition";
const ITEM_SIZE: usize = 256;
const ITEMS_PER_BLOB: NonZeroU64 = NZU64!(64);
#[derive(Clone, Copy)]
enum Mode {
Sync,
StartSync,
Commit,
}
impl Mode {
const fn name(self) -> &'static str {
match self {
Self::Sync => "sync",
Self::StartSync => "start_sync",
Self::Commit => "commit",
}
}
}
async fn cycle<J: Mutable<Item = FixedBytes<ITEM_SIZE>>>(
journal: J,
item: &FixedBytes<ITEM_SIZE>,
mode: Mode,
) -> J {
let (journal, _) = journal.append(item).await.unwrap();
match mode {
Mode::Sync => journal.sync().await.unwrap(),
Mode::StartSync => {
let (journal, handle) = journal.start_sync().await.unwrap();
handle.await.unwrap();
journal
}
Mode::Commit => journal.commit().await.unwrap(),
}
}
async fn run<J: Mutable<Item = FixedBytes<ITEM_SIZE>>>(
mut journal: J,
iters: u64,
mode: Mode,
) -> Duration {
let item = FixedBytes::new([0xAB; ITEM_SIZE]);
for _ in 0..2 {
journal = cycle(journal, &item, mode).await;
}
let mut elapsed = Duration::ZERO;
for _ in 0..iters {
let start = Instant::now();
journal = cycle(journal, &item, mode).await;
elapsed += start.elapsed();
}
journal.destroy().await.unwrap();
elapsed
}
fn bench_append_sync(c: &mut Criterion) {
let runner = tokio::Runner::default();
for fixed in [true, false] {
for mode in [Mode::Sync, Mode::StartSync, Mode::Commit] {
let kind = if fixed { "fixed" } else { "variable" };
c.bench_function(
&format!("{}/journal={kind} mode={}", module_path!(), mode.name()),
|b| {
b.to_async(&runner).iter_custom(|iters| async move {
let ctx = context::get::<commonware_runtime::tokio::Context>();
let storage = ctx.child("storage");
if fixed {
let journal =
get_fixed_journal::<ITEM_SIZE>(storage, PARTITION, ITEMS_PER_BLOB)
.await;
run(journal, iters, mode).await
} else {
let journal = get_variable_journal::<ITEM_SIZE>(
storage,
PARTITION,
ITEMS_PER_BLOB,
)
.await;
run(journal, iters, mode).await
}
});
},
);
}
}
}
criterion_group! {
name = benches;
config = Criterion::default().sample_size(30);
targets = bench_append_sync
}