99 lines
3.2 KiB
Rust
99 lines
3.2 KiB
Rust
//! Benchmarks for the chase subsystem.
|
|
//!
|
|
//! These are designed to retroactively validate the semi-naive and Skolem
|
|
//! work and catch future regressions. Each workload runs several chase
|
|
//! variants over the same input so relative numbers are meaningful.
|
|
|
|
use criterion::{BatchSize, Criterion, criterion_group, criterion_main};
|
|
use query_engine::chase::rule::RuleBuilder;
|
|
use query_engine::chase::{ChaseConfig, ChaseVariant, Rule, chase_with_config};
|
|
use query_engine::{Atom, Instance, Term};
|
|
|
|
fn chain_edges(n: usize) -> Instance {
|
|
(0..n)
|
|
.map(|i| {
|
|
Atom::new(
|
|
"Edge",
|
|
vec![
|
|
Term::constant(format!("n{}", i)),
|
|
Term::constant(format!("n{}", i + 1)),
|
|
],
|
|
)
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
fn transitive_closure_rules() -> Vec<Rule> {
|
|
let edge_to_path = RuleBuilder::new()
|
|
.when("Edge", vec![Term::var("X"), Term::var("Y")])
|
|
.then("Path", vec![Term::var("X"), Term::var("Y")])
|
|
.build();
|
|
let extend_path = RuleBuilder::new()
|
|
.when("Path", vec![Term::var("X"), Term::var("Y")])
|
|
.when("Edge", vec![Term::var("Y"), Term::var("Z")])
|
|
.then("Path", vec![Term::var("X"), Term::var("Z")])
|
|
.build();
|
|
vec![edge_to_path, extend_path]
|
|
}
|
|
|
|
fn bench_transitive_closure(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("transitive_closure_chain_20");
|
|
let instance = chain_edges(20);
|
|
let rules = transitive_closure_rules();
|
|
|
|
for (label, variant, semi) in [
|
|
("restricted_naive", ChaseVariant::Restricted, false),
|
|
("restricted_semi_naive", ChaseVariant::Restricted, true),
|
|
("standard_naive", ChaseVariant::Standard, false),
|
|
("standard_semi_naive", ChaseVariant::Standard, true),
|
|
] {
|
|
let config = ChaseConfig {
|
|
variant,
|
|
semi_naive: semi,
|
|
..Default::default()
|
|
};
|
|
group.bench_function(label, |b| {
|
|
b.iter_batched(
|
|
|| instance.clone(),
|
|
|inst| chase_with_config(inst, &rules, config.clone()),
|
|
BatchSize::SmallInput,
|
|
);
|
|
});
|
|
}
|
|
group.finish();
|
|
}
|
|
|
|
fn bench_existentials(c: &mut Criterion) {
|
|
let mut group = c.benchmark_group("existentials_50_people");
|
|
let instance: Instance = (0..50)
|
|
.map(|i| Atom::new("Person", vec![Term::constant(format!("p{}", i))]))
|
|
.collect();
|
|
let rule = RuleBuilder::new()
|
|
.when("Person", vec![Term::var("X")])
|
|
.then("HasId", vec![Term::var("X"), Term::var("Y")])
|
|
.build();
|
|
let rules = vec![rule];
|
|
|
|
for (label, variant) in [
|
|
("restricted", ChaseVariant::Restricted),
|
|
("skolem", ChaseVariant::Skolem),
|
|
] {
|
|
let config = ChaseConfig {
|
|
variant,
|
|
semi_naive: false,
|
|
..Default::default()
|
|
};
|
|
group.bench_function(label, |b| {
|
|
b.iter_batched(
|
|
|| instance.clone(),
|
|
|inst| chase_with_config(inst, &rules, config.clone()),
|
|
BatchSize::SmallInput,
|
|
);
|
|
});
|
|
}
|
|
group.finish();
|
|
}
|
|
|
|
criterion_group!(benches, bench_transitive_closure, bench_existentials);
|
|
criterion_main!(benches);
|