Phase 10: Monitoring and automated benchmarks

10.1: Add Criterion dev-dependency and benchmarks for:
  - matching_rules (100 rules)
  - ComputedStyle::compute (empty, 5 props)
  - resolve_string (no vars, 1 var, 3 vars)

10.3: Add --perf CLI flag and src/perf.rs module:
  - PerfScope drop-guard timed scopes (vdom, style, render)
  - Instrumented: VDOM eval (app.rs update), render (app.rs view),
    style matching (style.rs compute_cached)
  - Per-frame report printed to stderr at end of view()

10.2+10.4: Threshold check in perf report:
  - Prints warning if total > 16ms (60 FPS frame budget)

Refactor: Move Message enum to lib.rs so benchmarks can import
the public API. Added lib.rs as library root.
This commit is contained in:
Glint Dev
2026-07-24 19:58:58 +03:00
parent b6fa841d11
commit 938f05f59d
8 changed files with 389 additions and 26 deletions

99
benches/bench.rs Normal file
View File

@@ -0,0 +1,99 @@
use criterion::{criterion_group, criterion_main, Criterion};
fn bench_matching_rules(c: &mut Criterion) {
let mut group = c.benchmark_group("matching_rules");
group.sample_size(10);
group.bench_function("100_rules", |b| {
b.iter(|| {
let mut stylesheet = glint_runtime::interpreter::style::StyleSheet::new();
for i in 0..100 {
stylesheet.add_rule(
format!(".class-{}", i),
std::collections::HashMap::from([("color".into(), "red".into())]),
);
}
stylesheet.build_index();
let _ = stylesheet.matching_rules(
"Button",
None,
&["class-1"],
&[],
&Default::default(),
&[],
&[],
&std::collections::HashMap::new(),
);
})
});
group.finish();
}
fn bench_style_compute(c: &mut Criterion) {
let mut group = c.benchmark_group("computed_style");
group.sample_size(10);
group.bench_function("compute_empty", |b| {
b.iter(|| {
let _ = glint_runtime::interpreter::style::ComputedStyle::compute(
&[],
&[],
);
})
});
group.bench_function("compute_5_props", |b| {
let props: Vec<(std::borrow::Cow<'_, str>, std::borrow::Cow<'_, str>)> = vec![
("color".into(), "red".into()),
("padding".into(), "10px".into()),
("font-size".into(), "16px".into()),
("background".into(), "#fff".into()),
("width".into(), "100px".into()),
];
b.iter(|| {
let _ = glint_runtime::interpreter::style::ComputedStyle::compute(
&props,
&[],
);
})
});
group.finish();
}
fn bench_resolve_string(c: &mut Criterion) {
let mut group = c.benchmark_group("resolve_string");
group.sample_size(10);
let vars = std::collections::HashMap::from([
("name".to_string(), glint_runtime::interpreter::Value::Str("world".into())),
("count".to_string(), glint_runtime::interpreter::Value::Int(42)),
]);
group.bench_function("no_vars", |b| {
b.iter(|| {
use glint_runtime::interpreter::Interpreter;
let _ = Interpreter::resolve_string("hello world", &vars);
})
});
group.bench_function("1_var", |b| {
b.iter(|| {
use glint_runtime::interpreter::Interpreter;
let _ = Interpreter::resolve_string("Hello $name!", &vars);
})
});
group.bench_function("3_vars", |b| {
b.iter(|| {
use glint_runtime::interpreter::Interpreter;
let _ = Interpreter::resolve_string("$name has count $count and is $name", &vars);
})
});
group.finish();
}
criterion_group!(benches, bench_matching_rules, bench_style_compute, bench_resolve_string);
criterion_main!(benches);