mod common;
use std::cell::RefCell;
use std::rc::Rc;
use common::{block_on, with_rt};
use fluxbench::bench;
use fluxbench::prelude::*;
use pagedb::options::{OpenOptions, RetainPolicy};
use pagedb::vfs::memory::MemVfs;
use pagedb::{Db, RealmId};
const PAGE: usize = 4096;
const KEY_COUNT: usize = 1_000;
const REALM: RealmId = RealmId::new([0x51; 16]);
const KEK: [u8; 32] = [0xA5; 32];
const VALUE: &[u8] = b"authenticated-node-read";
thread_local! {
static STORE: RefCell<Option<MemVfs>> = const { RefCell::new(None) };
}
fn key(index: usize) -> Vec<u8> {
format!("node:{index:08}").into_bytes()
}
fn populated_store() -> MemVfs {
STORE.with(|cell| {
if cell.borrow().is_none() {
let vfs = MemVfs::new();
block_on(async {
let options =
OpenOptions::default().with_commit_history_retain(RetainPolicy::Disabled);
let db = Db::open(vfs.clone(), KEK, PAGE, REALM, options)
.await
.expect("open bench store");
let mut write = db.begin_write().await.expect("begin txn");
for index in 0..KEY_COUNT {
write.put(&key(index), VALUE).await.expect("insert");
}
write.commit().await.expect("commit");
});
*cell.borrow_mut() = Some(vfs);
}
cell.borrow().as_ref().expect("store initialised").clone()
})
}
fn cold_handle(store: &MemVfs) -> Db<MemVfs> {
block_on(async {
Db::open_read_only(store.clone(), KEK, PAGE, REALM, OpenOptions::default())
.await
.expect("open cold read-only handle")
})
}
#[bench(group = "pager/authenticated-node-read")]
fn cold_tree_get(b: &mut Bencher) {
let store = populated_store();
let handle: RefCell<Option<Rc<Db<MemVfs>>>> = RefCell::new(None);
let mut index = 0usize;
b.iter_with_setup(
|| {
let lookup_key = key(index % KEY_COUNT);
index = index.wrapping_add(1);
handle.borrow_mut().take();
*handle.borrow_mut() = Some(Rc::new(cold_handle(&store)));
lookup_key
},
|lookup_key| {
with_rt(|rt| {
rt.block_on(async {
let db = handle
.borrow()
.as_ref()
.map(Rc::clone)
.expect("handle opened in setup");
let read = db.begin_read().await.expect("begin read");
read.get(&lookup_key).await.expect("get")
})
})
},
);
}
fn main() {
if let Err(error) = fluxbench::run() {
eprintln!("fluxbench error: {error}");
std::process::exit(1);
}
}