use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
use std::hint::black_box;
use tensorlogic_adapters::{DomainInfo, EvolutionAnalyzer, PredicateInfo, SymbolTable};
fn create_schema(domains: usize, predicates_per_domain: usize) -> SymbolTable {
let mut table = SymbolTable::new();
for i in 0..domains {
table
.add_domain(DomainInfo::new(format!("Domain{}", i), 100))
.expect("unwrap");
}
for i in 0..domains {
let domain_name = format!("Domain{}", i);
for j in 0..predicates_per_domain {
let pred = PredicateInfo::new(
format!("pred_{}_{}", i, j),
vec![domain_name.clone(), domain_name.clone()],
);
table.add_predicate(pred).expect("unwrap");
}
}
table
}
fn create_modified_schema(
base: &SymbolTable,
additions: usize,
modifications: usize,
removals: usize,
) -> SymbolTable {
let mut table = base.clone();
for i in 0..additions {
table
.add_domain(DomainInfo::new(format!("NewDomain{}", i), 50))
.expect("unwrap");
}
for i in 0..modifications.min(base.domains.len()) {
let domain_name = format!("Domain{}", i);
if table.domains.contains_key(&domain_name) {
}
}
let pred_names: Vec<_> = table.predicates.keys().cloned().collect();
for _i in 0..removals.min(pred_names.len()) {
}
table
}
fn analysis_by_schema_size(c: &mut Criterion) {
let mut group = c.benchmark_group("analysis_by_size");
for size in [10, 50, 100, 200].iter() {
let old_schema = create_schema(*size, 5);
let new_schema = create_modified_schema(&old_schema, 5, 2, 3);
let total_components = size * 5;
group.throughput(Throughput::Elements(total_components as u64));
group.bench_with_input(
BenchmarkId::new("full_analysis", size),
&(old_schema, new_schema),
|b, (old, new)| {
b.iter(|| {
let analyzer = EvolutionAnalyzer::new(old, new);
let report = analyzer.analyze().expect("unwrap");
black_box(report);
});
},
);
}
group.finish();
}
fn analysis_by_change_percentage(c: &mut Criterion) {
let mut group = c.benchmark_group("analysis_by_change_pct");
let base_schema = create_schema(100, 5);
for change_pct in [1, 5, 10, 25, 50].iter() {
let changes = (100.0 * (*change_pct as f64) / 100.0) as usize;
let new_schema = create_modified_schema(&base_schema, changes, changes / 2, changes / 3);
group.bench_with_input(
BenchmarkId::new("changes", change_pct),
&(base_schema.clone(), new_schema),
|b, (old, new)| {
b.iter(|| {
let analyzer = EvolutionAnalyzer::new(old, new);
let report = analyzer.analyze().expect("unwrap");
black_box(report);
});
},
);
}
group.finish();
}
fn domain_analysis(c: &mut Criterion) {
let mut group = c.benchmark_group("domain_analysis");
for size in [50, 100, 200, 500].iter() {
let old_schema = create_schema(*size, 5);
let mut new_with_additions = old_schema.clone();
for i in 0..(*size / 10) {
new_with_additions
.add_domain(DomainInfo::new(format!("NewDomain{}", i), 50))
.expect("unwrap");
}
group.bench_with_input(
BenchmarkId::new("additions", size),
&(old_schema.clone(), new_with_additions),
|b, (old, new)| {
b.iter(|| {
let analyzer = EvolutionAnalyzer::new(old, new);
let report = analyzer.analyze().expect("unwrap");
black_box(report);
});
},
);
let new_with_modifications = old_schema.clone();
group.bench_with_input(
BenchmarkId::new("modifications", size),
&(old_schema.clone(), new_with_modifications),
|b, (old, new)| {
b.iter(|| {
let analyzer = EvolutionAnalyzer::new(old, new);
let report = analyzer.analyze().expect("unwrap");
black_box(report);
});
},
);
}
group.finish();
}
fn predicate_analysis(c: &mut Criterion) {
let mut group = c.benchmark_group("predicate_analysis");
for predicates_count in [100, 500, 1000].iter() {
let old_schema = create_schema(20, predicates_count / 20);
let mut new_schema = old_schema.clone();
for i in 0..(*predicates_count / 10) {
let pred = PredicateInfo::new(
format!("new_pred_{}", i),
vec!["Domain0".to_string(), "Domain1".to_string()],
);
new_schema.add_predicate(pred).expect("unwrap");
}
group.bench_with_input(
BenchmarkId::new("new_predicates", predicates_count),
&(old_schema, new_schema),
|b, (old, new)| {
b.iter(|| {
let analyzer = EvolutionAnalyzer::new(old, new);
let report = analyzer.analyze().expect("unwrap");
black_box(report);
});
},
);
}
group.finish();
}
fn migration_plan_generation(c: &mut Criterion) {
let mut group = c.benchmark_group("migration_plans");
for size in [50, 100, 200].iter() {
let old_schema = create_schema(*size, 5);
let new_schema = create_modified_schema(&old_schema, 10, 5, 5);
group.bench_with_input(
BenchmarkId::new("generate_plan", size),
&(old_schema, new_schema),
|b, (old, new)| {
b.iter(|| {
let analyzer = EvolutionAnalyzer::new(old, new);
let report = analyzer.analyze().expect("unwrap");
black_box(&report.migration_plan);
});
},
);
}
group.finish();
}
fn breaking_change_detection(c: &mut Criterion) {
let mut group = c.benchmark_group("breaking_changes");
for size in [50, 100, 200].iter() {
let old_schema = create_schema(*size, 5);
let mut compatible_schema = old_schema.clone();
compatible_schema
.add_domain(DomainInfo::new("Compatible", 100))
.expect("unwrap");
group.bench_with_input(
BenchmarkId::new("no_breaking", size),
&(old_schema.clone(), compatible_schema),
|b, (old, new)| {
b.iter(|| {
let analyzer = EvolutionAnalyzer::new(old, new);
let report = analyzer.analyze().expect("unwrap");
black_box(report.has_breaking_changes());
});
},
);
let breaking_schema = SymbolTable::new();
group.bench_with_input(
BenchmarkId::new("with_breaking", size),
&(old_schema, breaking_schema),
|b, (old, new)| {
b.iter(|| {
let analyzer = EvolutionAnalyzer::new(old, new);
let report = analyzer.analyze().expect("unwrap");
black_box(report.has_breaking_changes());
});
},
);
}
group.finish();
}
fn compatibility_report(c: &mut Criterion) {
let mut group = c.benchmark_group("compatibility_report");
for size in [50, 100, 200, 500].iter() {
let old_schema = create_schema(*size, 5);
let new_schema = create_modified_schema(&old_schema, 10, 5, 2);
group.bench_with_input(
BenchmarkId::new("full_report", size),
&(old_schema, new_schema),
|b, (old, new)| {
b.iter(|| {
let analyzer = EvolutionAnalyzer::new(old, new);
let report = analyzer.analyze().expect("unwrap");
black_box(report.has_breaking_changes());
black_box(&report.breaking_changes);
black_box(&report.backward_compatible_changes);
black_box(&report.migration_plan);
black_box(report.suggested_version_bump());
black_box(report.max_impact());
});
},
);
}
group.finish();
}
fn affected_predicate_detection(c: &mut Criterion) {
let mut group = c.benchmark_group("affected_predicates");
for size in [50, 100, 200].iter() {
let mut old_schema = SymbolTable::new();
for i in 0..*size {
old_schema
.add_domain(DomainInfo::new(format!("Domain{}", i), 100))
.expect("unwrap");
}
for i in 0..*size {
for j in 0..5 {
let domains = vec![format!("Domain{}", i), format!("Domain{}", (i + 1) % size)];
let pred = PredicateInfo::new(format!("pred_{}_{}", i, j), domains);
old_schema.add_predicate(pred).expect("unwrap");
}
}
let new_schema = SymbolTable::new();
group.bench_with_input(
BenchmarkId::new("find_affected", size),
&(old_schema, new_schema),
|b, (old, new)| {
b.iter(|| {
let analyzer = EvolutionAnalyzer::new(old, new);
let report = analyzer.analyze().expect("unwrap");
black_box(&report.breaking_changes);
});
},
);
}
group.finish();
}
criterion_group!(
benches,
analysis_by_schema_size,
analysis_by_change_percentage,
domain_analysis,
predicate_analysis,
migration_plan_generation,
breaking_change_detection,
compatibility_report,
affected_predicate_detection,
);
criterion_main!(benches);