use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; use derive_more::From; use proptest::strategy::{LazyJust, ValueTree}; use proptest::{collection::vec, prelude::*, test_runner::TestRunner}; use tree_edit_distance::{diff, Node, Tree}; #[derive(Debug, From)] struct TreeNode { weight: u8, children: Vec, } impl Node for TreeNode { type Kind = (); fn kind(&self) -> Self::Kind {} type Weight = u32; fn weight(&self) -> Self::Weight { self.weight.into() } } impl Tree for TreeNode { type Children<'c> = &'c [Self]; fn children(&self) -> Self::Children<'_> { &self.children } } fn tree(depth: u32, breadth: u32) -> impl Strategy { let size = (breadth.pow(depth + 1) - 1) / (breadth - 1) / 2; // half the maximum number of nodes (1u8.., LazyJust::new(Vec::new)) .prop_map_into() .prop_recursive(depth, size, breadth, move |inner| { (1u8.., vec(inner, ..=breadth as usize)).prop_map_into() }) } fn bench(c: &mut Criterion) { let mut runner = TestRunner::default(); let mut group = c.benchmark_group("n-ary tree diff"); for (d, b) in [(7, 2), (3, 6), (2, 15), (1, 255)] { group.bench_with_input(format!("depth={}/breadth={}", d, b), &tree(d, b), |b, s| { b.iter_batched_ref( || (s, s).new_tree(&mut runner).unwrap().current(), |(a, b)| diff(a, b), BatchSize::SmallInput, ) }); } group.finish(); } criterion_group!(benches, bench); criterion_main!(benches);