tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 1061HTML 997Markdown 12TOML 83120 Sutichaykuna

⎇ 0.3.x benches/grid.rs Rust · 154 siq'ikuna · 5.6 KB Ñawpa willay Pi imata llamkarqan ch'uya

Remove generated benchmarks (#358) 57672e96e · Nico Burns ·

1//! This file includes benchmarks for very large, pseudo-randomly generated trees
2use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
3use rand::prelude::*;
4use rand_chacha::ChaCha8Rng;
5use std::iter;
6use taffy::prelude::*;
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_with_children(Style { size: points(20.0), ..Default::default() }, &[]).unwrap()
12}
13
14fn random_grid_track<R: Rng>(rng: &mut R) -> TrackSizingFunction {
15    let switch: f32 = rng.gen_range(0.0..=1.0);
16    if switch < 0.1 {
17        auto()
18    } else if switch < 0.2 {
19        min_content()
20    } else if switch < 0.3 {
21        max_content()
22    } else if switch < 0.5 {
23        fr(1.0)
24    } else if switch < 0.6 {
25        minmax(points(0.0), fr(1.0))
26    } else if switch < 0.8 {
27        points(40.0)
28    } else {
29        percent(0.3)
30    }
31}
32
33fn random_nxn_grid_style<R: Rng>(rng: &mut R, track_count: usize) -> Style {
34    Style {
35        display: Display::Grid,
36        grid_template_columns: iter::from_fn(|| Some(random_grid_track(rng))).take(track_count).collect(),
37        grid_template_rows: iter::from_fn(|| Some(random_grid_track(rng))).take(track_count).collect(),
38        ..Default::default()
39    }
40}
41
42/// A tree with many children that have shallow depth
43fn build_grid_flat_hierarchy(col_count: usize, row_count: usize) -> (Taffy, Node) {
44    let mut taffy = Taffy::new();
45    let mut rng = ChaCha8Rng::seed_from_u64(12345);
46
47    let style = Style {
48        display: Display::Grid,
49        grid_template_columns: iter::from_fn(|| Some(random_grid_track(&mut rng))).take(col_count).collect(),
50        grid_template_rows: iter::from_fn(|| Some(random_grid_track(&mut rng))).take(row_count).collect(),
51        ..Default::default()
52    };
53
54    let children: Vec<_> =
55        iter::from_fn(|| Some(build_random_leaf(&mut taffy, &mut rng))).take(col_count * row_count).collect();
56
57    let root = taffy.new_with_children(style, children.as_slice()).unwrap();
58    (taffy, root)
59}
60
61/// A helper function to recursively construct a deep tree
62pub fn build_deep_grid_tree(
63    tree: &mut Taffy,
64    levels: usize,
65    track_count: usize,
66    create_leaf_node: &mut impl FnMut(&mut Taffy) -> Node,
67    create_container_node: &mut impl FnMut(&mut Taffy, Vec<Node>) -> Node,
68) -> Vec<Node> {
69    // The extra one is for a position:absolute child
70    let child_count = track_count * track_count;
71
72    if levels == 1 {
73        // Build leaf nodes
74        return (0..child_count).map(|_| create_leaf_node(tree)).collect();
75    }
76
77    // Add another layer to the tree
78    // Each child gets an equal amount of the remaining nodes
79    (0..child_count)
80        .map(|_| {
81            let sub_children =
82                build_deep_grid_tree(tree, levels - 1, track_count, create_leaf_node, create_container_node);
83            create_container_node(tree, sub_children)
84        })
85        .collect()
86}
87
88/// A tree with a higher depth for a more realistic scenario
89fn build_taffy_deep_grid_hierarchy(levels: usize, track_count: usize) -> (Taffy, Node) {
90    let mut rng = ChaCha8Rng::seed_from_u64(12345);
91    let mut build_leaf_node = |taffy: &mut Taffy| build_random_leaf(taffy, &mut rng);
92    let mut rng = ChaCha8Rng::seed_from_u64(12345);
93    let mut build_flex_node = |taffy: &mut Taffy, children: Vec<Node>| {
94        taffy.new_with_children(random_nxn_grid_style(&mut rng, track_count), &children).unwrap()
95    };
96
97    let mut taffy = Taffy::new();
98    let tree = build_deep_grid_tree(&mut taffy, levels, track_count, &mut build_leaf_node, &mut build_flex_node);
99    let root = taffy.new_with_children(Style::DEFAULT, &tree).unwrap();
100    (taffy, root)
101}
102
103fn taffy_benchmarks(c: &mut Criterion) {
104    let mut group = c.benchmark_group("grid/wide");
105    group.sample_size(10);
106    for track_count in [31usize, 100, 316].iter() {
107        group.bench_with_input(
108            BenchmarkId::new(format!("{c}x{c}", c = track_count), track_count.pow(2)),
109            track_count,
110            |b, &track_count| {
111                b.iter_batched(
112                    || build_grid_flat_hierarchy(track_count, track_count),
113                    |(mut taffy, root)| taffy.compute_layout(root, points(12000.0)).unwrap(),
114                    criterion::BatchSize::SmallInput,
115                )
116            },
117        );
118    }
119    group.finish();
120
121    let mut group = c.benchmark_group("grid/deep");
122    group.sample_size(10);
123    for (tracks, levels) in [(2, 5), (3, 4), (2, 7) /*, (3, 5)*/].iter() {
124        let children_per_level: usize = tracks * tracks;
125        group.bench_with_input(
126            BenchmarkId::new(format!("{c}x{c}", c = tracks), children_per_level.pow(*levels as u32)),
127            &(*levels, *tracks),
128            |b, &(levels, tracks)| {
129                b.iter_batched(
130                    || build_taffy_deep_grid_hierarchy(levels, tracks),
131                    |(mut taffy, root)| taffy.compute_layout(root, points(12000.0)).unwrap(),
132                    criterion::BatchSize::SmallInput,
133                )
134            },
135        );
136    }
137    group.finish();
138
139    let mut group = c.benchmark_group("grid/superdeep");
140    group.sample_size(10);
141    for levels in [100, 1000].iter() {
142        group.bench_with_input(BenchmarkId::new("1x1", levels), levels, |b, &levels| {
143            b.iter_batched(
144                || build_taffy_deep_grid_hierarchy(levels, 1),
145                |(mut taffy, root)| taffy.compute_layout(root, max_content()).unwrap(),
146                criterion::BatchSize::SmallInput,
147            )
148        });
149    }
150    group.finish();
151}
152
153criterion_group!(benches, taffy_benchmarks);
154criterion_main!(benches);