use criterion::{Criterion, criterion_group, criterion_main}; use ruin_ui::{ Color, Element, FlexDirection, LayoutCache, TextStyle, TextSystem, UiSize, layout_snapshot_with_cache, }; fn text_style() -> TextStyle { TextStyle::new(14.0, Color::rgb(0xFF, 0xFF, 0xFF)) } fn make_column_tree(n: usize) -> Element { let mut root = Element::new().direction(FlexDirection::Column); for i in 0..n { root = root.child(Element::text(format!("item {i}"), text_style())); } root } /// Static tree — nothing changes between frames. After one warmup frame, all /// subsequent frames should be near-zero cost (all cache hits). fn bench_static_tree(c: &mut Criterion) { let mut text_system = TextSystem::new(); let mut layout_cache = LayoutCache::new(); let root = make_column_tree(200); let size = UiSize::new(400.0, 4000.0); // Warm up cache. layout_snapshot_with_cache(1, size, &root, &mut text_system, &mut layout_cache); c.bench_function("layout_static_200_nodes", |b| { let mut version = 2u64; b.iter(|| { version += 1; layout_snapshot_with_cache(version, size, &root, &mut text_system, &mut layout_cache) }); }); } /// 200 nodes, one text content changes per frame — only one cache miss expected. fn bench_single_change(c: &mut Criterion) { let mut text_system = TextSystem::new(); let mut layout_cache = LayoutCache::new(); let size = UiSize::new(400.0, 4000.0); // Initial warmup. let root = make_column_tree(200); layout_snapshot_with_cache(1, size, &root, &mut text_system, &mut layout_cache); c.bench_function("layout_single_change_200_nodes", |b| { let mut counter = 0usize; let mut version = 2u64; b.iter(|| { counter += 1; version += 1; let mut tree = make_column_tree(200); tree.children[100] = Element::text(format!("changed {counter}"), text_style()); layout_snapshot_with_cache(version, size, &tree, &mut text_system, &mut layout_cache) }); }); } /// Scroll box with 500 items, 20 visible. Simulates a large list. fn bench_scroll_list(c: &mut Criterion) { let mut text_system = TextSystem::new(); let mut layout_cache = LayoutCache::new(); let item_height = 32.0; let viewport_height = 640.0; let n = 500; let mut scroll_box = Element::scroll_box(0.0).width(400.0).height(viewport_height); for i in 0..n { scroll_box = scroll_box.child( Element::new() .height(item_height) .child(Element::text(format!("list item {i}"), text_style())), ); } let root = Element::new().child(scroll_box); let size = UiSize::new(400.0, viewport_height); // Warm up. layout_snapshot_with_cache(1, size, &root, &mut text_system, &mut layout_cache); c.bench_function("layout_scroll_list_500_items", |b| { let mut version = 2u64; b.iter(|| { version += 1; layout_snapshot_with_cache(version, size, &root, &mut text_system, &mut layout_cache) }); }); } criterion_group!(benches, bench_static_tree, bench_single_change, bench_scroll_list); criterion_main!(benches);