119 lines
4.1 KiB
Rust
119 lines
4.1 KiB
Rust
|
|
//! Geomerge-specific benchmarks.
|
||
|
|
//!
|
||
|
|
//! Geomerge has a different shape from the KV adapters: theory-defined schema,
|
||
|
|
//! foreign-key value type, law validation at commit, and pending row id
|
||
|
|
//! resolution via `CommittedTx`. The three workloads here answer questions
|
||
|
|
//! specific to that shape:
|
||
|
|
//!
|
||
|
|
//! - `theory_load`: deserialize the bundled `paths.json` and build the
|
||
|
|
//! `GeomergeStorage`. One-shot, not parameterized.
|
||
|
|
//! - `insert_commit_n`: in one transaction, insert prerequisite Graphs / G0
|
||
|
|
//! / G1 rows and then N vertices in a host graph, then commit. Commit cost
|
||
|
|
//! reflects geomerge's law validation over the new state.
|
||
|
|
//! - `resolve_pending_n`: after a commit that produced N pending RowIds,
|
||
|
|
//! resolve each via `CommittedTx::resolve`. Measures the cost of mapping
|
||
|
|
//! in-flight ids to their post-commit form.
|
||
|
|
//!
|
||
|
|
//! Requires the `geomerge` feature; the bench is gated via
|
||
|
|
//! `required-features` in `Cargo.toml`.
|
||
|
|
|
||
|
|
#![allow(clippy::unwrap_used, clippy::expect_used)]
|
||
|
|
|
||
|
|
use criterion::{BatchSize, BenchmarkId, Criterion, black_box, criterion_group, criterion_main};
|
||
|
|
use geomerge::ir::FlatTheory;
|
||
|
|
use storage::adapters::geomerge::GeomergeStorage;
|
||
|
|
use storage::id::RowId;
|
||
|
|
use storage::value::Value;
|
||
|
|
use storage::{Storage, Transaction};
|
||
|
|
|
||
|
|
const PATHS_SCHEMA_JSON: &str =
|
||
|
|
include_str!("../../../external/geomerge/crates/geomerge/tests/data/paths.json");
|
||
|
|
|
||
|
|
const ROW_COUNTS: &[usize] = &[10, 100, 1_000];
|
||
|
|
|
||
|
|
fn load_theory() -> FlatTheory {
|
||
|
|
serde_json::from_str(PATHS_SCHEMA_JSON).unwrap()
|
||
|
|
}
|
||
|
|
|
||
|
|
fn fresh_storage() -> GeomergeStorage {
|
||
|
|
GeomergeStorage::from_theory(load_theory()).unwrap()
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Insert the schema-required Graphs, G0, and G1 rows. Returns the RowId of
|
||
|
|
/// the "host" graph that subsequent vertex inserts should reference.
|
||
|
|
fn build_prereqs(tx: &mut dyn Transaction) -> RowId {
|
||
|
|
let designated = tx.insert("Graphs", vec![]).unwrap();
|
||
|
|
let host = tx.insert("Graphs", vec![]).unwrap();
|
||
|
|
tx.insert("G0", vec![Value::Id(designated.clone())])
|
||
|
|
.unwrap();
|
||
|
|
tx.insert("G1", vec![Value::Id(designated)]).unwrap();
|
||
|
|
host
|
||
|
|
}
|
||
|
|
|
||
|
|
fn insert_n_vertices(tx: &mut dyn Transaction, host: &RowId, n: usize) -> Vec<RowId> {
|
||
|
|
let mut pending = Vec::with_capacity(n);
|
||
|
|
for _ in 0..n {
|
||
|
|
pending.push(tx.insert("G.V", vec![Value::Id(host.clone())]).unwrap());
|
||
|
|
}
|
||
|
|
pending
|
||
|
|
}
|
||
|
|
|
||
|
|
fn bench_theory_load(c: &mut Criterion) {
|
||
|
|
c.bench_function("theory_load", |b| {
|
||
|
|
b.iter(|| {
|
||
|
|
let theory = load_theory();
|
||
|
|
let storage = GeomergeStorage::from_theory(theory).unwrap();
|
||
|
|
black_box(storage);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
fn bench_insert_commit_n(c: &mut Criterion) {
|
||
|
|
let mut group = c.benchmark_group("insert_commit_n");
|
||
|
|
for &n in ROW_COUNTS {
|
||
|
|
group.bench_with_input(BenchmarkId::from_parameter(n), &n, |b, &n| {
|
||
|
|
b.iter_batched(
|
||
|
|
fresh_storage,
|
||
|
|
|mut storage| {
|
||
|
|
let mut tx = storage.transaction().unwrap();
|
||
|
|
let host = build_prereqs(&mut *tx);
|
||
|
|
let _ = insert_n_vertices(&mut *tx, &host, n);
|
||
|
|
tx.commit().unwrap();
|
||
|
|
black_box(storage);
|
||
|
|
},
|
||
|
|
BatchSize::SmallInput,
|
||
|
|
);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
group.finish();
|
||
|
|
}
|
||
|
|
|
||
|
|
fn bench_resolve_pending_n(c: &mut Criterion) {
|
||
|
|
let mut group = c.benchmark_group("resolve_pending_n");
|
||
|
|
for &n in ROW_COUNTS {
|
||
|
|
group.bench_with_input(BenchmarkId::from_parameter(n), &n, |b, &n| {
|
||
|
|
// One-time setup outside the timed window: build a CommittedTx
|
||
|
|
// with N pending vertex IDs.
|
||
|
|
let mut storage = fresh_storage();
|
||
|
|
let mut tx = storage.transaction().unwrap();
|
||
|
|
let host = build_prereqs(&mut *tx);
|
||
|
|
let pending = insert_n_vertices(&mut *tx, &host, n);
|
||
|
|
let committed = tx.commit().unwrap();
|
||
|
|
b.iter(|| {
|
||
|
|
for p in &pending {
|
||
|
|
black_box(committed.resolve(p));
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
}
|
||
|
|
group.finish();
|
||
|
|
}
|
||
|
|
|
||
|
|
criterion_group!(
|
||
|
|
benches,
|
||
|
|
bench_theory_load,
|
||
|
|
bench_insert_commit_n,
|
||
|
|
bench_resolve_pending_n
|
||
|
|
);
|
||
|
|
criterion_main!(benches);
|