use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
use pattern_core::Pattern;
fn create_large_flat_pattern(n: usize) -> Pattern<i32> {
let elements: Vec<Pattern<i32>> = (0..n).map(|i| Pattern::point(i as i32)).collect();
Pattern::pattern(0, elements)
}
fn create_deep_pattern(depth: usize) -> Pattern<i32> {
if depth == 0 {
Pattern::point(0)
} else {
Pattern::pattern(depth as i32, vec![create_deep_pattern(depth - 1)])
}
}
fn bench_any_value_early_match(c: &mut Criterion) {
let mut group = c.benchmark_group("any_value_short_circuit");
for size in [100, 1000, 10000].iter() {
let pattern = create_large_flat_pattern(*size);
group.bench_with_input(BenchmarkId::new("early_match", size), size, |b, _| {
b.iter(|| {
black_box(pattern.any_value(|v| *v == 5))
})
});
}
group.finish();
}
fn bench_any_value_late_match(c: &mut Criterion) {
let mut group = c.benchmark_group("any_value_late_match");
for size in [100, 1000, 10000].iter() {
let pattern = create_large_flat_pattern(*size);
group.bench_with_input(BenchmarkId::new("late_match", size), size, |b, _| {
b.iter(|| {
black_box(pattern.any_value(|v| *v == (*size as i32 - 10)))
})
});
}
group.finish();
}
fn bench_any_value_no_match(c: &mut Criterion) {
let mut group = c.benchmark_group("any_value_no_match");
for size in [100, 1000, 10000].iter() {
let pattern = create_large_flat_pattern(*size);
group.bench_with_input(BenchmarkId::new("no_match", size), size, |b, _| {
b.iter(|| {
black_box(pattern.any_value(|v| *v < 0))
})
});
}
group.finish();
}
fn bench_any_value_deep_nesting(c: &mut Criterion) {
let mut group = c.benchmark_group("any_value_deep_nesting");
for depth in [10, 50, 100].iter() {
let pattern = create_deep_pattern(*depth);
group.bench_with_input(BenchmarkId::new("deep_pattern", depth), depth, |b, _| {
b.iter(|| black_box(pattern.any_value(|v| *v > 50)))
});
}
group.finish();
}
fn bench_all_values_early_failure(c: &mut Criterion) {
let mut group = c.benchmark_group("all_values_short_circuit");
for size in [100, 1000, 10000].iter() {
let pattern = create_large_flat_pattern(*size);
group.bench_with_input(BenchmarkId::new("early_failure", size), size, |b, _| {
b.iter(|| {
black_box(pattern.all_values(|v| *v != 5))
})
});
}
group.finish();
}
fn bench_all_values_late_failure(c: &mut Criterion) {
let mut group = c.benchmark_group("all_values_late_failure");
for size in [100, 1000, 10000].iter() {
let pattern = create_large_flat_pattern(*size);
group.bench_with_input(BenchmarkId::new("late_failure", size), size, |b, _| {
b.iter(|| {
black_box(pattern.all_values(|v| *v != (*size as i32 - 10)))
})
});
}
group.finish();
}
fn bench_all_values_all_pass(c: &mut Criterion) {
let mut group = c.benchmark_group("all_values_all_pass");
for size in [100, 1000, 10000].iter() {
let pattern = create_large_flat_pattern(*size);
group.bench_with_input(BenchmarkId::new("all_pass", size), size, |b, _| {
b.iter(|| {
black_box(pattern.all_values(|v| *v >= 0))
})
});
}
group.finish();
}
fn bench_all_values_deep_nesting(c: &mut Criterion) {
let mut group = c.benchmark_group("all_values_deep_nesting");
for depth in [10, 50, 100].iter() {
let pattern = create_deep_pattern(*depth);
group.bench_with_input(BenchmarkId::new("deep_pattern", depth), depth, |b, _| {
b.iter(|| black_box(pattern.all_values(|v| *v > 0)))
});
}
group.finish();
}
fn bench_filter_operations(c: &mut Criterion) {
let mut group = c.benchmark_group("filter");
for size in [100, 1000, 10000].iter() {
let pattern = create_large_flat_pattern(*size);
group.bench_with_input(BenchmarkId::new("atomic_patterns", size), size, |b, _| {
b.iter(|| black_box(pattern.filter(|p| p.is_atomic())))
});
group.bench_with_input(BenchmarkId::new("value_predicate", size), size, |b, _| {
b.iter(|| black_box(pattern.filter(|p| p.value > 50)))
});
group.bench_with_input(
BenchmarkId::new("structural_predicate", size),
size,
|b, _| b.iter(|| black_box(pattern.filter(|p| p.length() > 0))),
);
group.bench_with_input(BenchmarkId::new("const_true", size), size, |b, _| {
b.iter(|| black_box(pattern.filter(|_| true)))
});
}
group.finish();
}
fn bench_filter_deep_nesting(c: &mut Criterion) {
let mut group = c.benchmark_group("filter_deep_nesting");
for depth in [10, 50, 100].iter() {
let pattern = create_deep_pattern(*depth);
group.bench_with_input(BenchmarkId::new("deep_pattern", depth), depth, |b, _| {
b.iter(|| black_box(pattern.filter(|p| p.value % 2 == 0)))
});
}
group.finish();
}
#[test]
fn verify_any_value_performance_target() {
use std::time::Instant;
let pattern = create_large_flat_pattern(10000);
let start = Instant::now();
let _ = pattern.any_value(|v| *v > 5000);
let duration = start.elapsed();
assert!(
duration.as_millis() < 100,
"any_value should complete in <100ms for 10,000 nodes, took {}ms",
duration.as_millis()
);
}
#[test]
fn verify_all_values_performance_target() {
use std::time::Instant;
let pattern = create_large_flat_pattern(10000);
let start = Instant::now();
let _ = pattern.all_values(|v| *v >= 0);
let duration = start.elapsed();
assert!(
duration.as_millis() < 100,
"all_values should complete in <100ms for 10,000 nodes, took {}ms",
duration.as_millis()
);
}
#[test]
fn verify_filter_performance_target() {
use std::time::Instant;
let pattern = create_large_flat_pattern(10000);
let start = Instant::now();
let _ = pattern.filter(|p| p.value > 5000);
let duration = start.elapsed();
assert!(
duration.as_millis() < 200,
"filter should complete in <200ms for 10,000 nodes, took {}ms",
duration.as_millis()
);
}
criterion_group!(
benches,
bench_any_value_early_match,
bench_any_value_late_match,
bench_any_value_no_match,
bench_any_value_deep_nesting,
bench_all_values_early_failure,
bench_all_values_late_failure,
bench_all_values_all_pass,
bench_all_values_deep_nesting,
bench_filter_operations,
bench_filter_deep_nesting,
);
criterion_main!(benches);