use morphorm::*;
use morphorm_ecs::*;
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
fn build_tree(world: &mut World, parent: Option<Entity>, children_per_node: usize, depth: usize) -> Entity {
let node = world.add(parent);
if parent.is_none() {
world.set_width(node, Units::Pixels(1000.0));
world.set_height(node, Units::Pixels(1000.0));
} else {
world.set_all_stretch(node);
}
let depth = depth.saturating_sub(1);
if depth > 0 {
for _ in 0..children_per_node {
build_tree(world, Some(node), children_per_node, depth);
}
return node;
}
Entity(0)
}
fn compute_node_count(children_per_node: usize, depth: usize, node_count: &mut usize) -> usize {
*node_count += 1;
let depth = depth.saturating_sub(1);
if depth > 0 {
for _ in 0..children_per_node {
compute_node_count(children_per_node, depth, node_count);
}
}
*node_count
}
fn morphorm_benchmarks(c: &mut Criterion) {
let mut group = c.benchmark_group("Shallow Tree");
group.sample_size(10);
let children_per_node = 10;
for depth in [4, 5, 6, 7].iter() {
let benchmark_id = BenchmarkId::new(
format!(
"Wide Shallow Bench. {children_per_node} children per node, depth: {depth}. Total nodes: {}.",
compute_node_count(children_per_node, *depth, &mut 0)
),
depth,
);
group.bench_with_input(benchmark_id, depth, |b, &depth| {
b.iter_batched(
|| {
let mut world = World::default();
let root = build_tree(&mut world, None, children_per_node, depth);
(world, root)
},
|(mut world, root)| root.layout(&mut world.cache, &world.tree, &world.store, &mut ()),
criterion::BatchSize::SmallInput,
)
});
}
group.finish();
let mut group = c.benchmark_group("Deep Tree");
group.sample_size(10);
let children_per_node = 2;
for depth in [10, 13, 17, 20].iter() {
let benchmark_id = BenchmarkId::new(
format!(
"Narrow Deep Bench. {children_per_node} children per node, depth: {depth}. Total nodes: {}.",
compute_node_count(children_per_node, *depth, &mut 0)
),
depth,
);
group.bench_with_input(benchmark_id, depth, |b, &depth| {
b.iter_batched(
|| {
let mut world = World::default();
let root = build_tree(&mut world, None, children_per_node, depth);
(world, root)
},
|(mut world, root)| root.layout(&mut world.cache, &world.tree, &world.store, &mut ()),
criterion::BatchSize::SmallInput,
)
});
}
group.finish();
let mut group = c.benchmark_group("Super Deep Tree");
group.sample_size(10);
let children_per_node = 1;
let depth = 1000usize;
let benchmark_id = BenchmarkId::new(
format!(
"Super Deep Bench. {children_per_node} child per node, depth: {depth}. Total nodes: {}.",
compute_node_count(children_per_node, depth, &mut 0)
),
depth,
);
group.bench_with_input(benchmark_id, &depth, |b, &depth| {
b.iter_batched(
|| {
let mut world = World::default();
let root = build_tree(&mut world, None, children_per_node, depth);
(world, root)
},
|(mut world, root)| root.layout(&mut world.cache, &world.tree, &world.store, &mut ()),
criterion::BatchSize::SmallInput,
)
});
group.finish();
let mut group = c.benchmark_group("Steady State Tree");
group.sample_size(20);
let children_per_node = 10;
let depth = 6usize;
let mut world = World::default();
let root = build_tree(&mut world, None, children_per_node, depth);
let benchmark_label = format!(
"Steady state bench. {children_per_node} children per node, depth: {depth}. Total nodes: {}.",
compute_node_count(children_per_node, depth, &mut 0)
);
group.bench_function(benchmark_label, |b| {
b.iter(|| {
root.layout(&mut world.cache, &world.tree, &world.store, &mut ());
})
});
group.finish();
}
criterion_group!(benches, morphorm_benchmarks);
criterion_main!(benches);