dreamstack/bench/benches/compiler_bench.rs
enzotar 7805b94704 feat: component registry with styled variants, dreamstack add/convert CLI, and showcase
- Phase 1: Component parser + codegen (emit_component_decl, emit_component_use, emit_match)
- Phase 2: 6 registry components (button, input, card, badge, dialog, toast)
- Phase 3: dreamstack add CLI with dependency resolution and --list/--all
- Phase 4: dreamstack convert TSX→DS transpiler with --shadcn GitHub fetch
- Phase 5: 120+ lines variant CSS (buttons, badges, cards, dialog, toast, input)
- New example: showcase.ds demonstrating all component styles
2026-02-26 13:27:49 -08:00

181 lines
5 KiB
Rust

/// DreamStack Compiler & Layout Benchmarks
///
/// Measures:
/// - Compiler pipeline throughput (parse → analyze → emit)
/// - Signal graph construction at various scales
/// - Cassowary constraint solver with varying constraint counts
use criterion::{black_box, criterion_group, criterion_main, Criterion, BenchmarkId};
// ── Compiler pipeline benchmarks ────────────────────────────
fn counter_source() -> &'static str {
r#"
let count = 0
on click { count = count + 1 }
view main = column [
text { "Count: " + count }
button("Increment") { on: click }
]
"#
}
fn todo_source() -> &'static str {
r#"
let todos = []
let input = ""
let filter = "all"
on addTodo {
todos = todos + [{ text: input, done: false }]
input = ""
}
on toggleTodo {
todos = todos
}
view main = column [
row [
text { input }
button("Add") { on: addTodo }
]
column [
for todo in todos {
row [
text { todo.text }
]
}
]
row [
button("All") { on: toggleTodo }
button("Active") { on: toggleTodo }
button("Done") { on: toggleTodo }
]
]
"#
}
/// Generate a stress-test source with N signals and derived values.
fn signal_chain_source(n: usize) -> String {
let mut src = String::new();
src.push_str("let s0 = 0\n");
for i in 1..n {
src.push_str(&format!("let s{i} = s{} + 1\n", i - 1));
}
src.push_str(&format!(
"view main = column [\n text {{ \"Last: \" + s{} }}\n]\n",
n - 1
));
src
}
/// Generate a fan-out source: 1 root signal, N derived dependents.
fn fan_out_source(n: usize) -> String {
let mut src = String::from("let root = 0\n");
for i in 0..n {
src.push_str(&format!("let d{i} = root + {i}\n"));
}
// View shows last derived
src.push_str(&format!(
"view main = column [\n text {{ \"d0: \" + d0 }}\n]\n",
));
src
}
fn compile_source(source: &str) -> String {
let program = ds_parser::parse(source).expect("parse failed");
let (graph, views) = ds_analyzer::analyze(&program);
ds_codegen::JsEmitter::emit_html(&program, &graph, &views)
}
fn bench_compiler_pipeline(c: &mut Criterion) {
let mut group = c.benchmark_group("compiler_pipeline");
group.bench_function("counter", |b| {
let src = counter_source();
b.iter(|| compile_source(black_box(src)));
});
group.bench_function("todo", |b| {
let src = todo_source();
b.iter(|| compile_source(black_box(src)));
});
group.finish();
}
fn bench_signal_chain(c: &mut Criterion) {
let mut group = c.benchmark_group("signal_chain");
for &n in &[10, 50, 100, 500, 1000] {
let src = signal_chain_source(n);
group.bench_with_input(BenchmarkId::from_parameter(n), &src, |b, src| {
b.iter(|| compile_source(black_box(src)));
});
}
group.finish();
}
fn bench_fan_out(c: &mut Criterion) {
let mut group = c.benchmark_group("fan_out");
for &n in &[10, 50, 100, 500, 1000] {
let src = fan_out_source(n);
group.bench_with_input(BenchmarkId::from_parameter(n), &src, |b, src| {
b.iter(|| compile_source(black_box(src)));
});
}
group.finish();
}
// ── Constraint solver benchmarks ────────────────────────────
fn bench_constraint_solver(c: &mut Criterion) {
use ds_layout::{LayoutSolver, Variable, Constraint, Strength};
let mut group = c.benchmark_group("constraint_solver");
for &n in &[10, 50, 100, 500] {
group.bench_with_input(BenchmarkId::new("panel_chain", n), &n, |b, &n| {
b.iter(|| {
let mut solver = LayoutSolver::new();
// Create a chain of N panels: each starts where the previous ends
let mut vars = Vec::new();
for _ in 0..n {
let x = Variable::new();
let w = Variable::new();
vars.push((x, w));
}
// First panel at x=0, width=100
solver.add_constraint(Constraint::eq_const(vars[0].0, 0.0, Strength::Required));
solver.add_constraint(Constraint::eq_const(vars[0].1, 100.0, Strength::Required));
// Each subsequent panel: x_i = x_{i-1} + w_{i-1}
for i in 1..n {
solver.add_constraint(Constraint::sum_eq(
vars[i - 1].0,
vars[i - 1].1,
0.0,
Strength::Required,
));
solver.add_constraint(Constraint::eq_const(vars[i].1, 100.0, Strength::Required));
}
solver.solve();
black_box(solver.get_value(vars[n - 1].0));
});
});
}
group.finish();
}
criterion_group!(
benches,
bench_compiler_pipeline,
bench_signal_chain,
bench_fan_out,
bench_constraint_solver,
);
criterion_main!(benches);