Skip to content

Commit

Permalink
Tree creation benchmarks (#401)
Browse files Browse the repository at this point in the history
* Add tree creation benchmarks

* Rename allocation benchmark to tree_creation
  • Loading branch information
nicoburns committed Mar 20, 2023
1 parent 2942c70 commit 08aa501
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 0 deletions.
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ taffy = { path = ".", features = ["random"] }
lto = true
panic = 'abort'

[[bench]]
name = "tree_creation"
path = "benches/tree_creation.rs"
harness = false

[[bench]]
name = "flexbox"
path = "benches/flexbox.rs"
Expand Down
1 change: 1 addition & 0 deletions benches/helpers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pub mod yoga_helpers;

/// A helper function to recursively construct a deep tree
#[allow(dead_code)]
pub fn build_deep_tree<T, N>(
tree: &mut T,
max_nodes: u32,
Expand Down
12 changes: 12 additions & 0 deletions benches/helpers/yoga_helpers.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![allow(dead_code)]
use slotmap::{DefaultKey, SlotMap};

pub mod yg {
Expand All @@ -12,6 +13,17 @@ mod tf {
pub use taffy::prelude::*;
}

pub fn new_default_style_with_children(
tree: &mut SlotMap<DefaultKey, yg::Node>,
children: Vec<DefaultKey>,
) -> DefaultKey {
let mut node = yg::Node::new();
for (i, child) in children.into_iter().enumerate() {
node.insert_child(&mut tree[child], i as u32);
}
tree.insert(node)
}

pub fn new_with_children(
tree: &mut SlotMap<DefaultKey, yg::Node>,
style: &tf::Style,
Expand Down
99 changes: 99 additions & 0 deletions benches/tree_creation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//! This file includes benchmarks for tree creation
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use rand::prelude::*;
use rand_chacha::ChaCha8Rng;
use taffy::prelude::*;
use taffy::style::Style;

mod helpers;

#[cfg(feature = "yoga_benchmark")]
use helpers::yoga_helpers;
#[cfg(feature = "yoga_benchmark")]
use slotmap::SlotMap;
#[cfg(feature = "yoga_benchmark")]
use yoga_helpers::yg;

/// Build a random leaf node
fn build_random_leaf(taffy: &mut Taffy) -> Node {
taffy.new_with_children(Style::DEFAULT, &[]).unwrap()
}

/// A tree with many children that have shallow depth
fn build_taffy_flat_hierarchy(total_node_count: u32, use_with_capacity: bool) -> (Taffy, Node) {
let mut taffy = if use_with_capacity { Taffy::with_capacity(total_node_count as usize) } else { Taffy::new() };
let mut rng = ChaCha8Rng::seed_from_u64(12345);
let mut children = Vec::new();
let mut node_count = 0;

while node_count < total_node_count {
let sub_children_count = rng.gen_range(1..=4);
let sub_children: Vec<Node> = (0..sub_children_count).map(|_| build_random_leaf(&mut taffy)).collect();
let node = taffy.new_with_children(Style::DEFAULT, &sub_children).unwrap();

children.push(node);
node_count += 1 + sub_children_count;
}

let root = taffy.new_with_children(Style::DEFAULT, children.as_slice()).unwrap();
(taffy, root)
}

#[cfg(feature = "yoga_benchmark")]
/// A tree with many children that have shallow depth
fn build_yoga_flat_hierarchy(total_node_count: u32) -> (yg::YogaTree, Node) {
let mut tree = SlotMap::new();
let mut rng = ChaCha8Rng::seed_from_u64(12345);
let mut children = Vec::new();
let mut node_count = 0;

while node_count < total_node_count {
let sub_children_count = rng.gen_range(1..=4);
let sub_children: Vec<Node> =
(0..sub_children_count).map(|_| yoga_helpers::new_default_style_with_children(&mut tree, vec![])).collect();
let node = yoga_helpers::new_default_style_with_children(&mut tree, sub_children);

children.push(node);
node_count += 1 + sub_children_count;
}

let root = yoga_helpers::new_default_style_with_children(&mut tree, children);
(tree, root)
}

fn taffy_benchmarks(c: &mut Criterion) {
let mut group = c.benchmark_group("Tree creation");
for node_count in [1_000u32, 10_000, 100_000].iter() {
#[cfg(feature = "yoga_benchmark")]
let benchmark_id = BenchmarkId::new(format!("Yoga"), node_count);
#[cfg(feature = "yoga_benchmark")]
group.bench_with_input(benchmark_id, node_count, |b, &node_count| {
b.iter(|| {
let (taffy, root) = build_yoga_flat_hierarchy(node_count);
std::hint::black_box(taffy);
std::hint::black_box(root);
})
});
let benchmark_id = BenchmarkId::new(format!("Taffy::new"), node_count);
group.bench_with_input(benchmark_id, node_count, |b, &node_count| {
b.iter(|| {
let (tree, root) = build_taffy_flat_hierarchy(node_count, false);
std::hint::black_box(tree);
std::hint::black_box(root);
})
});

let benchmark_id = BenchmarkId::new(format!("Taffy::with_capacity"), node_count);
group.bench_with_input(benchmark_id, node_count, |b, &node_count| {
b.iter(|| {
let (tree, root) = build_taffy_flat_hierarchy(node_count, true);
std::hint::black_box(tree);
std::hint::black_box(root);
})
});
}
group.finish();
}

criterion_group!(benches, taffy_benchmarks);
criterion_main!(benches);

0 comments on commit 08aa501

Please sign in to comment.