gioser

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 1061HTML 997Markdown 12TOML 83120 Definiciones

Tree creation benchmarks (#401)

* Add tree creation benchmarks

* Rename allocation benchmark to tree_creation

08aa50102b44242362de80dd1f4eb0c9b208c758 · por Nico Burns · (hace 3 años) · padre 2942c70b3 · ver el árbol en este commit

Delta semántico · 6

benches/helpers/yoga_helpers.rs

benches/tree_creation.rs

4 archivos · +117 −0

diff --git a/Cargo.toml b/Cargo.toml
index 9ed7c4871..918fcdd47 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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"
diff --git a/benches/helpers/mod.rs b/benches/helpers/mod.rs
index 66269b571..617fc6897 100644
--- a/benches/helpers/mod.rs
+++ b/benches/helpers/mod.rs
@@ -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,
diff --git a/benches/helpers/yoga_helpers.rs b/benches/helpers/yoga_helpers.rs
index 165ebdfea..787ea569e 100644
--- a/benches/helpers/yoga_helpers.rs
+++ b/benches/helpers/yoga_helpers.rs
@@ -1,3 +1,4 @@
+#![allow(dead_code)]
 use slotmap::{DefaultKey, SlotMap};
 
 pub mod yg {
@@ -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,
diff --git a/benches/tree_creation.rs b/benches/tree_creation.rs
new file mode 100644
index 000000000..10ce6a898
--- /dev/null
+++ b/benches/tree_creation.rs
@@ -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);