use std::hint::black_box;
use std::num::NonZeroU64;
use crate::relation::RelationKind;
use crate::test_support::{
make_batch_raw, make_schema_u64_i64, pk_only_schema, relation_fixture, RelationFixture, TID,
};
use gnitz_wire::{PkColList, Probe, TypeCode};
use gnitz_zset::repr::{Batch, BatchBuilder};
use gnitz_zset::schema::SchemaDescriptor;
const RUNS: usize = 8;
const ROWS: u64 = 400_000;
fn fixture(val_of: impl Fn(u64) -> i64) -> RelationFixture {
let schema = make_schema_u64_i64();
let rounds = (0..RUNS as u64).map(|round| {
let rows: Vec<_> = (round..ROWS).step_by(RUNS).map(|id| (id, 1, val_of(id))).collect();
make_batch_raw(&schema, &rows)
});
let r = relation_fixture(RelationKind::BaseTable, schema, &[1], rounds);
let table = r.relation(TID).unwrap().table();
assert_eq!((table.all_shard_arcs().len(), table.runs().count()), (0, RUNS));
r
}
fn keys(schema: &SchemaDescriptor, vals: impl Iterator<Item = u64>) -> Batch {
let mut bb = BatchBuilder::new(schema);
for v in vals {
bb.begin_row(v as u128, 1);
bb.end_row();
}
bb.finish()
}
#[test]
#[ignore = "benchmark; run with --release --ignored --nocapture --test-threads=1"]
fn probe_bench() {
let counter = gnitz_foundation::perf::Counter::instructions();
let cell = |label: &str, r: &RelationFixture, probe: Probe, keys: Batch, want: u64| {
black_box(r.probe(TID, probe, &keys).unwrap());
let (reply, instructions) = counter.measure(|| r.probe(TID, probe, &keys).unwrap());
assert_eq!(reply.len() as u64, want, "{label}: reply rows");
println!(
"probe_bench {label:<28} {:>8} keys {:>8} rows {:>9.1} instr/key",
keys.len(),
reply.len(),
instructions as f64 / keys.len() as f64
);
};
let index = |cap| Probe::Index(PkColList::from_slice(&[1]), NonZeroU64::new(cap).unwrap());
let span = pk_only_schema(&[TypeCode::I64]);
let pk = pk_only_schema(&[TypeCode::U64]);
let unique = fixture(|id| id as i64 * 16);
let held = || (0..ROWS).map(|id| id * 16);
cell("index, hits", &unique, index(1), keys(&span, held()), ROWS);
cell(
"index, one hit",
&unique,
index(1),
keys(&span, held().skip(1).take(1)),
1,
);
let between = keys(&span, held().map(|v| v + 8));
cell("index, lone misses", &unique, index(1), between, 0);
let unheld = keys(&span, (0..ROWS).filter(|v| v % 16 != 0));
cell("index, runs of misses", &unique, index(1), unheld, 0);
cell("pk", &unique, Probe::Pk, keys(&pk, 0..ROWS), ROWS);
cell("pk, misses", &unique, Probe::Pk, keys(&pk, ROWS..2 * ROWS), 0);
cell("pk column", &unique, Probe::PkColumn(1), keys(&pk, 0..ROWS), ROWS);
let groups = fixture(|id| (id / 4) as i64);
let vals = || keys(&span, 0..ROWS / 4);
cell("index, 4 holders, cap 8", &groups, index(8), vals(), ROWS);
cell("index, 4 holders, cap 1", &groups, index(1), vals(), ROWS / 4);
}