Disable super-deep benchmarks (0.1 is too slow to complete these at all) (#280)
1//! This file includes benchmarks for very large, pseudo-randomly generated trees
2use criterion::{criterion_group, criterion_main, Criterion};
3use rand::prelude::*;
4use rand_chacha::ChaCha8Rng;
5use taffy::prelude::*;
6use taffy::randomizable::Randomizeable;
7use taffy::style::Style;
8
9/// Build a random leaf node
10fn build_random_leaf(taffy: &mut Taffy, rng: &mut ChaCha8Rng) -> Node {
11 taffy.new_node(Style::random(rng), &[]).unwrap()
12}
13
14/// A tree with many children that have shallow depth
15fn build_flat_hierarchy(taffy: &mut Taffy, total_node_count: u32) -> Node {
16 let mut rng = ChaCha8Rng::seed_from_u64(12345);
17 let mut children = Vec::new();
18 let mut node_count = 0;
19
20 while node_count < total_node_count {
21 let sub_children_count = rng.gen_range(1..=4);
22 let sub_children: Vec<Node> = (0..sub_children_count).map(|_| build_random_leaf(taffy, &mut rng)).collect();
23 let node = taffy.new_node(Style::random(&mut rng), &sub_children).unwrap();
24
25 children.push(node);
26 node_count += 1 + sub_children_count;
27 }
28
29 taffy.new_node(Style { ..Default::default() }, children.as_slice()).unwrap()
30}
31
32/// A helper function to recursively construct a deep tree
33fn build_deep_tree(
34 taffy: &mut Taffy,
35 max_nodes: u32,
36 branching_factor: u32,
37 create_leaf_node: &mut impl FnMut(&mut Taffy) -> Node,
38 create_flex_node: &mut impl FnMut(&mut Taffy, Vec<Node>) -> Node,
39) -> Vec<Node> {
40 if max_nodes <= branching_factor {
41 // Build leaf nodes
42 return (0..max_nodes).map(|_| create_leaf_node(taffy)).collect();
43 }
44
45 // Add another layer to the tree
46 // Each child gets an equal amount of the remaining nodes
47 (0..branching_factor)
48 .map(|_| {
49 let max_nodes = (max_nodes - branching_factor) / branching_factor;
50 let sub_children = build_deep_tree(taffy, max_nodes, branching_factor, create_leaf_node, create_flex_node);
51 create_flex_node(taffy, sub_children)
52 })
53 .collect()
54}
55
56/// A tree with a higher depth for a more realistic scenario
57fn build_deep_hierarchy(taffy: &mut Taffy, node_count: u32, branching_factor: u32) -> Node {
58 let mut rng = ChaCha8Rng::seed_from_u64(12345);
59 let mut build_leaf_node = |taffy: &mut Taffy| build_random_leaf(taffy, &mut rng);
60 let mut rng = ChaCha8Rng::seed_from_u64(12345);
61 let mut build_flex_node =
62 |taffy: &mut Taffy, children: Vec<Node>| taffy.new_node(Style::random(&mut rng), &children).unwrap();
63
64 let tree = build_deep_tree(taffy, node_count, branching_factor, &mut build_leaf_node, &mut build_flex_node);
65
66 taffy.new_node(Style { ..Default::default() }, &tree).unwrap()
67}
68
69/// A deep tree that matches the shape and styling that yoga use on their benchmarks
70fn build_yoga_deep_hierarchy(taffy: &mut Taffy, node_count: u32, branching_factor: u32) -> Node {
71 let style = Style {
72 size: Size { width: Dimension::Points(10.0), height: Dimension::Points(10.0) },
73 flex_grow: 1.0,
74 ..Default::default()
75 };
76 let mut build_leaf_node = |taffy: &mut Taffy| taffy.new_node(style.clone(), &[]).unwrap();
77 let mut build_flex_node =
78 |taffy: &mut Taffy, children: Vec<Node>| taffy.new_node(style.clone(), &children).unwrap();
79
80 let tree = build_deep_tree(taffy, node_count, branching_factor, &mut build_leaf_node, &mut build_flex_node);
81 let root = taffy.new_node(Style { ..Default::default() }, &tree).unwrap();
82
83 root
84}
85
86fn taffy_benchmarks(c: &mut Criterion) {
87 let mut group = c.benchmark_group("yoga benchmarks");
88 group.sample_size(10);
89
90 group.bench_function("10 nodes", |b| {
91 b.iter_batched(
92 || {
93 let mut taffy = Taffy::new();
94 let root = build_yoga_deep_hierarchy(&mut taffy, 10, 10);
95 (taffy, root)
96 },
97 |(mut taffy, root)| taffy.compute_layout(root, Size::undefined()).unwrap(),
98 criterion::BatchSize::SmallInput,
99 )
100 });
101
102 group.bench_function("100 nodes", |b| {
103 b.iter_batched(
104 || {
105 let mut taffy = Taffy::new();
106 let root = build_yoga_deep_hierarchy(&mut taffy, 100, 10);
107 (taffy, root)
108 },
109 |(mut taffy, root)| taffy.compute_layout(root, Size::undefined()).unwrap(),
110 criterion::BatchSize::SmallInput,
111 )
112 });
113
114 group.bench_function("1_000 nodes", |b| {
115 b.iter_batched(
116 || {
117 let mut taffy = Taffy::new();
118 let root = build_yoga_deep_hierarchy(&mut taffy, 1_000, 10);
119 (taffy, root)
120 },
121 |(mut taffy, root)| taffy.compute_layout(root, Size::undefined()).unwrap(),
122 criterion::BatchSize::SmallInput,
123 )
124 });
125
126 group.bench_function("10_000 nodes", |b| {
127 b.iter_batched(
128 || {
129 let mut taffy = Taffy::new();
130 let root = build_yoga_deep_hierarchy(&mut taffy, 10_000, 10);
131 (taffy, root)
132 },
133 |(mut taffy, root)| taffy.compute_layout(root, Size::undefined()).unwrap(),
134 criterion::BatchSize::SmallInput,
135 )
136 });
137
138 group.bench_function("100_000 nodes", |b| {
139 b.iter_batched(
140 || {
141 let mut taffy = Taffy::new();
142 let root = build_yoga_deep_hierarchy(&mut taffy, 100_000, 10);
143 (taffy, root)
144 },
145 |(mut taffy, root)| taffy.compute_layout(root, Size::undefined()).unwrap(),
146 criterion::BatchSize::LargeInput,
147 )
148 });
149
150 // group.bench_function("1_000_000 nodes", |b| {
151 // b.iter_batched(
152 // || {
153 // let mut taffy = Taffy::new();
154 // let root = build_yoga_deep_hierarchy(&mut taffy, 1_000_000, 10);
155 // (taffy, root)
156 // },
157 // |(mut taffy, root)| taffy.compute_layout(root, Size::undefined()).unwrap(),
158 // criterion::BatchSize::LargeInput,
159 // )
160 // });
161 drop(group);
162
163 // Decrease sample size, because the tasks take longer
164 let mut group = c.benchmark_group("big trees (wide)");
165 group.sample_size(10);
166
167 group.bench_function("10 nodes (2-level hierarchy)", |b| {
168 b.iter_batched(
169 || {
170 let mut taffy = Taffy::new();
171 let root = build_flat_hierarchy(&mut taffy, 10);
172 (taffy, root)
173 },
174 |(mut taffy, root)| taffy.compute_layout(root, Size::undefined()).unwrap(),
175 criterion::BatchSize::SmallInput,
176 )
177 });
178
179 group.bench_function("100 nodes (2-level hierarchy)", |b| {
180 b.iter_batched(
181 || {
182 let mut taffy = Taffy::new();
183 let root = build_flat_hierarchy(&mut taffy, 100);
184 (taffy, root)
185 },
186 |(mut taffy, root)| taffy.compute_layout(root, Size::undefined()).unwrap(),
187 criterion::BatchSize::SmallInput,
188 )
189 });
190
191 group.bench_function("1_000 nodes (2-level hierarchy)", |b| {
192 b.iter_batched(
193 || {
194 let mut taffy = Taffy::new();
195 let root = build_flat_hierarchy(&mut taffy, 1_000);
196 (taffy, root)
197 },
198 |(mut taffy, root)| taffy.compute_layout(root, Size::undefined()).unwrap(),
199 criterion::BatchSize::SmallInput,
200 )
201 });
202
203 group.bench_function("10_000 nodes (2-level hierarchy)", |b| {
204 b.iter_batched(
205 || {
206 let mut taffy = Taffy::new();
207 let root = build_flat_hierarchy(&mut taffy, 10_000);
208 (taffy, root)
209 },
210 |(mut taffy, root)| taffy.compute_layout(root, Size::undefined()).unwrap(),
211 criterion::BatchSize::LargeInput,
212 )
213 });
214
215 group.bench_function("100_000 nodes (2-level hierarchy)", |b| {
216 b.iter_batched(
217 || {
218 let mut taffy = Taffy::new();
219 let root = build_flat_hierarchy(&mut taffy, 100_000);
220 (taffy, root)
221 },
222 |(mut taffy, root)| taffy.compute_layout(root, Size::undefined()).unwrap(),
223 criterion::BatchSize::LargeInput,
224 )
225 });
226
227 group.bench_function("100_000 nodes (7-level hierarchy)", |b| {
228 b.iter_batched(
229 || {
230 let mut taffy = Taffy::new();
231 let root = build_deep_hierarchy(&mut taffy, 100_000, 7);
232 (taffy, root)
233 },
234 |(mut taffy, root)| taffy.compute_layout(root, Size::undefined()).unwrap(),
235 criterion::BatchSize::LargeInput,
236 )
237 });
238
239 drop(group);
240
241 // Decrease sample size, because the tasks take longer
242 let mut group = c.benchmark_group("big trees (deep)");
243 group.sample_size(10);
244
245 group.bench_function("4000 nodes (12-level hierarchy)", |b| {
246 b.iter_batched(
247 || {
248 let mut taffy = Taffy::new();
249 let root = build_deep_hierarchy(&mut taffy, 4000, 2);
250 (taffy, root)
251 },
252 |(mut taffy, root)| taffy.compute_layout(root, Size::undefined()).unwrap(),
253 criterion::BatchSize::SmallInput,
254 )
255 });
256
257 group.bench_function("10_000 nodes (14-level hierarchy)", |b| {
258 b.iter_batched(
259 || {
260 let mut taffy = Taffy::new();
261 let root = build_deep_hierarchy(&mut taffy, 10_000, 2);
262 (taffy, root)
263 },
264 |(mut taffy, root)| taffy.compute_layout(root, Size::undefined()).unwrap(),
265 criterion::BatchSize::SmallInput,
266 )
267 });
268
269 // group.bench_function("100_000 nodes (17-level hierarchy)", |b| {
270 // b.iter_batched(
271 // || {
272 // let mut taffy = Taffy::new();
273 // let root = build_deep_hierarchy(&mut taffy, 100_000, 2);
274 // (taffy, root)
275 // },
276 // |(mut taffy, root)| taffy.compute_layout(root, Size::undefined()).unwrap(),
277 // criterion::BatchSize::LargeInput,
278 // )
279 // });
280
281 // group.bench_function("1_000_000 nodes (20-level hierarchy)", |b| {
282 // b.iter_batched(
283 // || {
284 // let mut taffy = Taffy::new();
285 // let root = build_deep_hierarchy(&mut taffy, 1_000_000, 2);
286 // (taffy, root)
287 // },
288 // |(mut taffy, root)| taffy.compute_layout(root, Size::undefined()).unwrap(),
289 // criterion::BatchSize::LargeInput,
290 // )
291 // });
292
293 drop(group);
294
295 // let mut group = c.benchmark_group("super deep trees");
296 // group.sample_size(10);
297
298 // group.bench_function("100 nodes (100-level hierarchy)", |b| {
299 // b.iter_batched(
300 // || {
301 // let mut taffy = Taffy::new();
302 // let root = build_deep_hierarchy(&mut taffy, 100, 1);
303 // (taffy, root)
304 // },
305 // |(mut taffy, root)| taffy.compute_layout(root, Size::undefined()).unwrap(),
306 // criterion::BatchSize::SmallInput,
307 // )
308 // });
309
310 // group.bench_function("1_000 nodes (1000-level hierarchy)", |b| {
311 // b.iter_batched(
312 // || {
313 // let mut taffy = Taffy::new();
314 // let root = build_deep_hierarchy(&mut taffy, 1_000, 1);
315 // (taffy, root)
316 // },
317 // |(mut taffy, root)| taffy.compute_layout(root, Size::undefined()).unwrap(),
318 // criterion::BatchSize::SmallInput,
319 // )
320 // });
321}
322
323criterion_group!(benches, taffy_benchmarks);
324criterion_main!(benches);