@@ -7,10 +7,10 @@ use taffy::style::Style as TaffyStyle;
77
88use taffy_benchmarks:: { BuildTreeExt , FixedStyleGenerator , GenStyle , TaffyTreeBuilder } ;
99
10+ #[ cfg( feature = "taffy03" ) ]
11+ use taffy_benchmarks:: taffy_03_helpers:: Taffy03TreeBuilder ;
1012#[ cfg( feature = "yoga" ) ]
11- use taffy_benchmarks:: yoga_helpers;
12- #[ cfg( feature = "yoga" ) ]
13- use yoga_helpers:: { yg, YogaTreeBuilder } ;
13+ use taffy_benchmarks:: yoga_helpers:: YogaTreeBuilder ;
1414
1515fn random_dimension ( rng : & mut impl Rng ) -> Dimension {
1616 match rng. gen_range ( 0.0 ..=1.0 ) {
@@ -19,6 +19,8 @@ fn random_dimension(rng: &mut impl Rng) -> Dimension {
1919 _ => Dimension :: Percent ( rng. gen_range ( 0.0 ..1.0 ) ) ,
2020 }
2121}
22+
23+ #[ derive( Clone ) ]
2224pub struct RandomStyleGenerator ;
2325impl GenStyle < TaffyStyle > for RandomStyleGenerator {
2426 fn create_leaf_style ( & mut self , rng : & mut impl Rng ) -> TaffyStyle {
@@ -29,112 +31,78 @@ impl GenStyle<TaffyStyle> for RandomStyleGenerator {
2931 }
3032}
3133
32- /// A deep tree that matches the shape and styling that yoga use on their benchmarks
33- fn build_flat_hierarchy < G : GenStyle < TaffyStyle > , TreeBuilder : BuildTreeExt < G > > (
34- target_node_count : u32 ,
35- style_generator : impl FnOnce ( ) -> G ,
36- ) -> ( TreeBuilder :: Tree , TreeBuilder :: Node ) {
37- let tree_builder = TreeBuilder :: new ( style_generator ( ) ) ;
38- tree_builder. build_flat_hierarchy ( target_node_count)
39- }
40-
41- /// A deep tree that matches the shape and styling that yoga use on their benchmarks
42- fn build_deep_hierarchy < G : GenStyle < TaffyStyle > , TreeBuilder : BuildTreeExt < G > > (
43- node_count : u32 ,
44- branching_factor : u32 ,
45- style_generator : impl FnOnce ( ) -> G ,
46- ) -> ( TreeBuilder :: Tree , TreeBuilder :: Node ) {
47- let tree_builder = TreeBuilder :: new ( style_generator ( ) ) ;
48- tree_builder. build_deep_hierarchy ( node_count, branching_factor)
34+ macro_rules! run_benchmark {
35+ ( $TreeBuilder: ty, $tree_builder_name: literal, $benchmark_name: expr, $group: ident, $builder: ident, $params: expr, $generate_style: expr, $generate_tree: expr) => {
36+ let benchmark_id = BenchmarkId :: new( format!( "{} {}" , $tree_builder_name, $benchmark_name) , $params) ;
37+ $group. bench_with_input( benchmark_id, $params, |b, _params| {
38+ b. iter_batched(
39+ || -> $TreeBuilder {
40+ let mut $builder = <$TreeBuilder>:: new( $generate_style( ) ) ;
41+ $generate_tree;
42+ $builder
43+ } ,
44+ |mut builder| builder. compute_layout( None , None ) ,
45+ criterion:: BatchSize :: SmallInput ,
46+ )
47+ } ) ;
48+ } ;
4949}
5050
51- /// A deep tree that matches the shape and styling that yoga use on their benchmarks
52- fn build_super_deep_hierarchy < G : GenStyle < TaffyStyle > , TreeBuilder : BuildTreeExt < G > > (
53- depth : u32 ,
54- nodes_per_level : u32 ,
55- style_generator : impl FnOnce ( ) -> G ,
56- ) -> ( TreeBuilder :: Tree , TreeBuilder :: Node ) {
57- let tree_builder = TreeBuilder :: new ( style_generator ( ) ) ;
58- tree_builder. build_super_deep_hierarchy ( depth, nodes_per_level)
59- }
51+ macro_rules! benchmark_each_library {
52+ ( $benchmark_name: expr, $group: ident, $builder: ident, $params: expr, $generate_style: expr, $generate_tree: expr) => {
53+ #[ cfg( feature = "yoga" ) ]
54+ run_benchmark!( YogaTreeBuilder <_, _>, "Yoga" , $benchmark_name, $group, $builder, $params, $generate_style, $generate_tree) ;
55+ #[ cfg( feature = "taffy03" ) ]
56+ run_benchmark!( Taffy03TreeBuilder <_, _>, "Taffy 0.3" , $benchmark_name, $group, $builder, $params, $generate_style, $generate_tree) ;
6057
61- /// A deep tree that matches the shape and styling that yoga use on their benchmarks
62- fn build_huge_nested_hierarchy < G : GenStyle < TaffyStyle > , TreeBuilder : BuildTreeExt < G > > (
63- node_count : u32 ,
64- branching_factor : u32 ,
65- style_generator : impl FnOnce ( ) -> G ,
66- ) -> ( TreeBuilder :: Tree , TreeBuilder :: Node ) {
67- let tree_builder = TreeBuilder :: new ( style_generator ( ) ) ;
68- tree_builder. build_deep_hierarchy ( node_count, branching_factor)
58+ run_benchmark!( TaffyTreeBuilder <_, _>, "Taffy 0.4" , $benchmark_name, $group, $builder, $params, $generate_style, $generate_tree) ;
59+ } ;
6960}
7061
7162fn huge_nested_benchmarks ( c : & mut Criterion ) {
72- let mut group = c. benchmark_group ( "yoga 'huge nested'" ) ;
73- let style = Style { size : length ( 10.0 ) , flex_grow : 1.0 , ..Default :: default ( ) } ;
74- let style_gen = || FixedStyleGenerator ( style. clone ( ) ) ;
75- for node_count in [
63+ let node_counts = [
7664 #[ cfg( feature = "small" ) ]
7765 1_000u32 ,
7866 10_000 ,
7967 #[ cfg( feature = "large" ) ]
8068 100_000 ,
81- ]
82- . iter ( )
83- {
84- #[ cfg( feature = "yoga" ) ]
85- group. bench_with_input ( BenchmarkId :: new ( "Yoga" , node_count) , node_count, |b, & node_count| {
86- b. iter_batched (
87- || build_huge_nested_hierarchy :: < _ , YogaTreeBuilder < _ , _ > > ( node_count, 10 , style_gen) ,
88- |( mut tree, root) | {
89- tree[ root] . calculate_layout ( f32:: INFINITY , f32:: INFINITY , yg:: Direction :: LTR ) ;
90- } ,
91- criterion:: BatchSize :: SmallInput ,
92- )
93- } ) ;
94- group. bench_with_input ( BenchmarkId :: new ( "Taffy" , node_count) , node_count, |b, & node_count| {
95- b. iter_batched (
96- || build_huge_nested_hierarchy :: < _ , TaffyTreeBuilder < _ , _ > > ( node_count, 10 , style_gen) ,
97- |( mut taffy, root) | taffy. compute_layout ( root, Size :: MAX_CONTENT ) . unwrap ( ) ,
98- criterion:: BatchSize :: SmallInput ,
99- )
100- } ) ;
69+ ] ;
70+
71+ let mut group = c. benchmark_group ( "yoga 'huge nested'" ) ;
72+ let style = Style { size : length ( 10.0 ) , flex_grow : 1.0 , ..Default :: default ( ) } ;
73+ for node_count in node_counts. iter ( ) {
74+ benchmark_each_library ! (
75+ "" ,
76+ group,
77+ builder,
78+ node_count,
79+ || FixedStyleGenerator ( style. clone( ) ) ,
80+ builder. build_deep_hierarchy( * node_count, 10 )
81+ ) ;
10182 }
10283 group. finish ( ) ;
10384}
10485
10586fn wide_benchmarks ( c : & mut Criterion ) {
106- // Decrease sample size, because the tasks take longer
107- let mut group = c. benchmark_group ( "Wide tree" ) ;
108- group. sample_size ( 10 ) ;
109- for node_count in [
87+ let node_counts = [
11088 #[ cfg( feature = "small" ) ]
11189 1_000u32 ,
11290 10_000 ,
11391 #[ cfg( feature = "large" ) ]
11492 100_000 ,
115- ]
116- . iter ( )
117- {
118- #[ cfg( feature = "yoga" ) ]
119- let benchmark_id = BenchmarkId :: new ( format ! ( "Yoga (2-level hierarchy)" ) , node_count) ;
120- #[ cfg( feature = "yoga" ) ]
121- group. bench_with_input ( benchmark_id, node_count, |b, & node_count| {
122- b. iter_batched (
123- || build_flat_hierarchy :: < _ , YogaTreeBuilder < _ , _ > > ( node_count, || RandomStyleGenerator ) ,
124- |( mut tree, root) | {
125- tree[ root] . calculate_layout ( f32:: INFINITY , f32:: INFINITY , yg:: Direction :: LTR ) ;
126- } ,
127- criterion:: BatchSize :: SmallInput ,
128- )
129- } ) ;
130- let benchmark_id = BenchmarkId :: new ( format ! ( "Taffy (2-level hierarchy)" ) , node_count) ;
131- group. bench_with_input ( benchmark_id, node_count, |b, & node_count| {
132- b. iter_batched (
133- || build_flat_hierarchy :: < _ , TaffyTreeBuilder < _ , _ > > ( node_count, || RandomStyleGenerator ) ,
134- |( mut taffy, root) | taffy. compute_layout ( root, Size :: MAX_CONTENT ) . unwrap ( ) ,
135- criterion:: BatchSize :: SmallInput ,
136- )
137- } ) ;
93+ ] ;
94+
95+ let mut group = c. benchmark_group ( "Wide tree" ) ;
96+ group. sample_size ( 10 ) ; // Decrease sample size, because the tasks take longer
97+ for node_count in node_counts. iter ( ) {
98+ benchmark_each_library ! (
99+ "(2-level hierarchy)" ,
100+ group,
101+ builder,
102+ node_count,
103+ || RandomStyleGenerator ,
104+ builder. build_flat_hierarchy( * node_count)
105+ ) ;
138106 }
139107 group. finish ( ) ;
140108}
@@ -150,64 +118,52 @@ fn deep_random_benchmarks(c: &mut Criterion) {
150118 ( 100_000 , "(17-level hierarchy)" ) ,
151119 ] ;
152120 for ( node_count, label) in benches. iter ( ) {
153- #[ cfg( feature = "yoga" ) ]
154- group. bench_with_input ( BenchmarkId :: new ( format ! ( "Yoga {label}" ) , node_count) , node_count, |b, & node_count| {
155- b. iter_batched (
156- || build_deep_hierarchy :: < _ , YogaTreeBuilder < _ , _ > > ( node_count, 2 , || RandomStyleGenerator ) ,
157- |( mut tree, root) | {
158- tree[ root] . calculate_layout ( f32:: INFINITY , f32:: INFINITY , yg:: Direction :: LTR ) ;
159- } ,
160- criterion:: BatchSize :: SmallInput ,
161- )
162- } ) ;
163- group. bench_with_input ( BenchmarkId :: new ( format ! ( "Taffy {label}" ) , node_count) , node_count, |b, & node_count| {
164- b. iter_batched (
165- || build_deep_hierarchy :: < _ , TaffyTreeBuilder < _ , _ > > ( node_count, 2 , || RandomStyleGenerator ) ,
166- |( mut taffy, root) | taffy. compute_layout ( root, Size :: MAX_CONTENT ) . unwrap ( ) ,
167- criterion:: BatchSize :: SmallInput ,
168- )
169- } ) ;
121+ benchmark_each_library ! (
122+ label,
123+ group,
124+ builder,
125+ node_count,
126+ || RandomStyleGenerator ,
127+ builder. build_deep_hierarchy( * node_count, 2 )
128+ ) ;
170129 }
171130 group. finish ( ) ;
172131}
173132
174133fn deep_auto_benchmarks ( c : & mut Criterion ) {
175- // Decrease sample size, because the tasks take longer
176- let mut group = c. benchmark_group ( "Deep tree (auto size)" ) ;
177- group. sample_size ( 10 ) ;
178- let style = Style { flex_grow : 1.0 , margin : length ( 10.0 ) , ..Default :: default ( ) } ;
179- let style_gen = || FixedStyleGenerator ( style. clone ( ) ) ;
180134 let benches = [
181135 ( 4000 , "(12-level hierarchy)" ) ,
182136 ( 10_000 , "(14-level hierarchy)" ) ,
183137 #[ cfg( feature = "large" ) ]
184138 ( 100_000 , "(17-level hierarchy)" ) ,
185139 ] ;
140+ let style = Style { flex_grow : 1.0 , margin : length ( 10.0 ) , ..Default :: default ( ) } ;
141+
142+ let mut group = c. benchmark_group ( "Deep tree (auto size)" ) ;
143+ group. sample_size ( 10 ) ; // Decrease sample size, because the tasks take longer
186144 for ( node_count, label) in benches. iter ( ) {
187- #[ cfg( feature = "yoga" ) ]
188- group. bench_with_input ( BenchmarkId :: new ( format ! ( "Yoga {label}" ) , node_count) , node_count, |b, & node_count| {
189- b. iter_batched (
190- || build_deep_hierarchy :: < _ , YogaTreeBuilder < _ , _ > > ( node_count, 2 , style_gen) ,
191- |( mut tree, root) | {
192- tree[ root] . calculate_layout ( f32:: INFINITY , f32:: INFINITY , yg:: Direction :: LTR ) ;
193- } ,
194- criterion:: BatchSize :: SmallInput ,
195- )
196- } ) ;
197- group. bench_with_input ( BenchmarkId :: new ( format ! ( "Taffy {label}" ) , node_count) , node_count, |b, & node_count| {
198- b. iter_batched (
199- || build_deep_hierarchy :: < _ , TaffyTreeBuilder < _ , _ > > ( node_count, 2 , style_gen) ,
200- |( mut taffy, root) | taffy. compute_layout ( root, Size :: MAX_CONTENT ) . unwrap ( ) ,
201- criterion:: BatchSize :: SmallInput ,
202- )
203- } ) ;
145+ benchmark_each_library ! (
146+ label,
147+ group,
148+ builder,
149+ node_count,
150+ || FixedStyleGenerator ( style. clone( ) ) ,
151+ builder. build_deep_hierarchy( * node_count, 2 )
152+ ) ;
204153 }
205154 group. finish ( ) ;
206155}
207156
208157fn super_deep_benchmarks ( c : & mut Criterion ) {
209- let mut group = c. benchmark_group ( "super deep" ) ;
210- group. sample_size ( 10 ) ;
158+ let benches = [
159+ #[ cfg( feature = "small" ) ]
160+ 50u32 ,
161+ 100 ,
162+ #[ cfg( feature = "large" ) ]
163+ 200 ,
164+ ] ;
165+
166+ #[ derive( Clone ) ]
211167 struct SuperDeepStyleGen ;
212168 impl GenStyle < TaffyStyle > for SuperDeepStyleGen {
213169 fn create_leaf_style ( & mut self , _rng : & mut impl Rng ) -> TaffyStyle {
@@ -219,40 +175,45 @@ fn super_deep_benchmarks(c: &mut Criterion) {
219175 self . create_leaf_style ( rng)
220176 }
221177 }
222- for depth in [
223- #[ cfg( feature = "small" ) ]
224- 50u32 ,
225- 100 ,
226- #[ cfg( feature = "large" ) ]
227- 200 ,
228- ]
229- . iter ( )
230- {
178+
179+ let mut group = c. benchmark_group ( "super deep" ) ;
180+ group. sample_size ( 10 ) ;
181+
182+ for depth in benches. iter ( ) {
231183 // Yoga is particularly slow at these benchmarks, so we gate them behind a separate feature flag
232184 #[ cfg( all( feature = "yoga" , feature = "yoga-super-deep" ) ) ]
233- group. bench_with_input ( BenchmarkId :: new ( "Yoga" , depth) , depth, |b, & depth| {
234- b. iter_batched (
235- || build_super_deep_hierarchy :: < _ , YogaTreeBuilder < _ , _ > > ( depth, 3 , || SuperDeepStyleGen ) ,
236- |( mut tree, root) | {
237- tree[ root] . calculate_layout ( 800. , 800. , yg:: Direction :: LTR ) ;
238- } ,
239- criterion:: BatchSize :: SmallInput ,
240- )
241- } ) ;
242- group. bench_with_input ( BenchmarkId :: new ( "Taffy" , depth) , depth, |b, & depth| {
243- b. iter_batched (
244- || build_super_deep_hierarchy :: < _ , TaffyTreeBuilder < _ , _ > > ( depth, 3 , || SuperDeepStyleGen ) ,
245- |( mut taffy, root) | {
246- taffy
247- . compute_layout (
248- root,
249- Size { width : AvailableSpace :: Definite ( 800. ) , height : AvailableSpace :: Definite ( 800. ) } ,
250- )
251- . unwrap ( )
252- } ,
253- criterion:: BatchSize :: SmallInput ,
254- )
255- } ) ;
185+ run_benchmark ! (
186+ YogaTreeBuilder <_, _>,
187+ "Yoga" ,
188+ "" ,
189+ group,
190+ builder,
191+ depth,
192+ || SuperDeepStyleGen ,
193+ builder. build_super_deep_hierarchy( * depth, 3 )
194+ ) ;
195+ #[ cfg( feature = "taffy03" ) ]
196+ run_benchmark ! (
197+ Taffy03TreeBuilder <_, _>,
198+ "Taffy 0.3" ,
199+ "" ,
200+ group,
201+ builder,
202+ depth,
203+ || SuperDeepStyleGen ,
204+ builder. build_super_deep_hierarchy( * depth, 3 )
205+ ) ;
206+
207+ run_benchmark ! (
208+ TaffyTreeBuilder <_, _>,
209+ "Taffy 0.4" ,
210+ "" ,
211+ group,
212+ builder,
213+ depth,
214+ || SuperDeepStyleGen ,
215+ builder. build_super_deep_hierarchy( * depth, 3 )
216+ ) ;
256217 }
257218 group. finish ( ) ;
258219}
0 commit comments