use commonware_runtime::{
telemetry::metrics::{Metric, Registered, Registration},
Metrics, Name, Supervisor,
};
use commonware_storage::{
index::{ordered, partitioned, unordered, Unordered},
translator::{Cap, EightCap},
};
use commonware_utils::TestRng;
use rand::Rng;
use std::{
hint::black_box,
time::{Duration, Instant},
};
const DEFAULT_ITEMS: [u64; 2] = [20_000_000, 100_000_000];
const SEED: u64 = 0;
#[derive(Clone)]
struct DummyMetrics;
impl Supervisor for DummyMetrics {
fn child(&self, _: &'static str) -> Self {
Self
}
fn with_attribute(self, _: &'static str, _: impl std::fmt::Display) -> Self {
Self
}
fn name(&self) -> Name {
Name::default()
}
}
impl Metrics for DummyMetrics {
fn register<N: Into<String>, H: Into<String>, M: Metric>(
&self,
_: N,
_: H,
metric: M,
) -> Registered<M> {
Registered::with_registration(metric, Registration::from(()))
}
fn encode(&self) -> String {
String::new()
}
}
fn measure<I: Unordered<Value = u64>>(mut index: I, items: u64) -> (Duration, Duration) {
let mut rng = TestRng::new(SEED);
let start = Instant::now();
for value in 0..items {
index.insert(&rng.next_u64().to_be_bytes(), value);
}
let insert = start.elapsed();
let mut rng = TestRng::new(SEED);
let start = Instant::now();
for _ in 0..items {
black_box(index.get(&rng.next_u64().to_be_bytes()).next().is_some());
}
let lookup = start.elapsed();
(insert, lookup)
}
fn main() {
let argv: Vec<String> = std::env::args().skip(1).collect();
let args: Vec<u64> = argv.iter().filter_map(|a| a.parse().ok()).collect();
let only: Vec<String> = argv
.into_iter()
.filter(|a| a.parse::<u64>().is_err() && !a.starts_with('-'))
.collect();
let sizes = if !args.is_empty() {
args
} else if cfg!(huge_bench) {
DEFAULT_ITEMS.to_vec()
} else {
eprintln!(
"index_scale is opt-in; pass key counts (e.g. `-- 500000000`), or build with \
`--cfg huge_bench` for the default 20M/100M tier"
);
return;
};
for items in sizes {
println!("index_scale: items={items}");
macro_rules! run {
($name:literal, $index:expr) => {{
if only.is_empty() || only.iter().any(|v| v.as_str() == $name) {
let (insert, lookup) = measure($index, items);
println!(
" {:<24} insert={} ns/op lookup={} ns/op",
$name,
insert.as_nanos() / items as u128,
lookup.as_nanos() / items as u128,
);
}
}};
}
run!(
"partitioned_ordered_3",
partitioned::ordered::Index::<_, _, 3>::new(DummyMetrics, Cap::<5>::new())
);
run!("unordered", unordered::Index::new(DummyMetrics, EightCap));
run!(
"partitioned_unordered_1",
partitioned::unordered::Index::<_, _, 1>::new(DummyMetrics, Cap::<7>::new())
);
run!(
"partitioned_unordered_2",
partitioned::unordered::Index::<_, _, 2>::new(DummyMetrics, Cap::<6>::new())
);
run!("ordered", ordered::Index::new(DummyMetrics, EightCap));
}
}