xref: /aosp_15_r20/external/flatbuffers/tests/rust_usage_test/benches/flatbuffers_benchmarks.rs (revision 890232f25432b36107d06881e0a25aaa6b473652)
1 /*
2  * Copyright 2018 Google Inc. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 use bencher::{benchmark_group, Bencher};
18 use flatbuffers;
19 
20 #[allow(dead_code, unused_imports)]
21 #[path = "../../monster_test/mod.rs"]
22 mod monster_test_generated;
23 pub use monster_test_generated::my_game;
24 
traverse_canonical_buffer(bench: &mut Bencher)25 fn traverse_canonical_buffer(bench: &mut Bencher) {
26     let owned_data = {
27         let mut builder = &mut flatbuffers::FlatBufferBuilder::new();
28         create_serialized_example_with_generated_code(&mut builder, true);
29         builder.finished_data().to_vec()
30     };
31     let data = &owned_data[..];
32     let n = data.len() as u64;
33     bench.iter(|| {
34         traverse_serialized_example_with_generated_code(data);
35     });
36     bench.bytes = n;
37 }
38 
create_canonical_buffer_then_reset(bench: &mut Bencher)39 fn create_canonical_buffer_then_reset(bench: &mut Bencher) {
40     let mut builder = &mut flatbuffers::FlatBufferBuilder::new();
41     // warmup
42     create_serialized_example_with_generated_code(&mut builder, true);
43     let n = builder.finished_data().len() as u64;
44     builder.reset();
45 
46     bench.iter(|| {
47         let _ = create_serialized_example_with_generated_code(&mut builder, true);
48         builder.reset();
49     });
50 
51     bench.bytes = n;
52 }
53 
54 #[inline(always)]
create_serialized_example_with_generated_code( builder: &mut flatbuffers::FlatBufferBuilder, finish: bool, ) -> usize55 fn create_serialized_example_with_generated_code(
56     builder: &mut flatbuffers::FlatBufferBuilder,
57     finish: bool,
58 ) -> usize {
59     let s0 = builder.create_string("test1");
60     let s1 = builder.create_string("test2");
61     let t0_name = builder.create_string("Barney");
62     let t1_name = builder.create_string("Fred");
63     let t2_name = builder.create_string("Wilma");
64     let t0 = my_game::example::Monster::create(
65         builder,
66         &my_game::example::MonsterArgs {
67             hp: 1000,
68             name: Some(t0_name),
69             ..Default::default()
70         },
71     );
72     let t1 = my_game::example::Monster::create(
73         builder,
74         &my_game::example::MonsterArgs {
75             name: Some(t1_name),
76             ..Default::default()
77         },
78     );
79     let t2 = my_game::example::Monster::create(
80         builder,
81         &my_game::example::MonsterArgs {
82             name: Some(t2_name),
83             ..Default::default()
84         },
85     );
86     let mon = {
87         let name = builder.create_string("MyMonster");
88         let fred_name = builder.create_string("Fred");
89         let inventory = builder.create_vector_direct(&[0u8, 1, 2, 3, 4]);
90         let test4 = builder.create_vector_direct(&[
91             my_game::example::Test::new(10, 20),
92             my_game::example::Test::new(30, 40),
93         ]);
94         let pos = my_game::example::Vec3::new(
95             1.0,
96             2.0,
97             3.0,
98             3.0,
99             my_game::example::Color::Green,
100             &my_game::example::Test::new(5i16, 6i8),
101         );
102         let args = my_game::example::MonsterArgs {
103             hp: 80,
104             mana: 150,
105             name: Some(name),
106             pos: Some(&pos),
107             test_type: my_game::example::Any::Monster,
108             test: Some(
109                 my_game::example::Monster::create(
110                     builder,
111                     &my_game::example::MonsterArgs {
112                         name: Some(fred_name),
113                         ..Default::default()
114                     },
115                 )
116                 .as_union_value(),
117             ),
118             inventory: Some(inventory),
119             test4: Some(test4),
120             testarrayofstring: Some(builder.create_vector(&[s0, s1])),
121             testarrayoftables: Some(builder.create_vector(&[t0, t1, t2])),
122             ..Default::default()
123         };
124         my_game::example::Monster::create(builder, &args)
125     };
126     if finish {
127         my_game::example::finish_monster_buffer(builder, mon);
128     }
129 
130     builder.finished_data().len()
131 
132     // make it do some work
133     // if builder.finished_data().len() == 0 { panic!("bad benchmark"); }
134 }
135 
136 #[inline(always)]
blackbox<T>(t: T) -> T137 fn blackbox<T>(t: T) -> T {
138     // encapsulate this in case we need to turn it into a noop
139     bencher::black_box(t)
140 }
141 
142 #[inline(always)]
traverse_serialized_example_with_generated_code(bytes: &[u8])143 fn traverse_serialized_example_with_generated_code(bytes: &[u8]) {
144     let m = unsafe { my_game::example::root_as_monster_unchecked(bytes) };
145     blackbox(m.hp());
146     blackbox(m.mana());
147     blackbox(m.name());
148     let pos = m.pos().unwrap();
149     blackbox(pos.x());
150     blackbox(pos.y());
151     blackbox(pos.z());
152     blackbox(pos.test1());
153     blackbox(pos.test2());
154     let pos_test3 = pos.test3();
155     blackbox(pos_test3.a());
156     blackbox(pos_test3.b());
157     blackbox(m.test_type());
158     let table2 = m.test().unwrap();
159     let monster2 = my_game::example::Monster::init_from_table(table2);
160     blackbox(monster2.name());
161     blackbox(m.inventory());
162     blackbox(m.test4());
163     let testarrayoftables = m.testarrayoftables().unwrap();
164     blackbox(testarrayoftables.get(0).hp());
165     blackbox(testarrayoftables.get(0).name());
166     blackbox(testarrayoftables.get(1).name());
167     blackbox(testarrayoftables.get(2).name());
168     let testarrayofstring = m.testarrayofstring().unwrap();
169     blackbox(testarrayofstring.get(0));
170     blackbox(testarrayofstring.get(1));
171 }
172 
create_string_10(bench: &mut Bencher)173 fn create_string_10(bench: &mut Bencher) {
174     let builder = &mut flatbuffers::FlatBufferBuilder::with_capacity(1 << 20);
175     let mut i = 0;
176     bench.iter(|| {
177         builder.create_string("foobarbaz"); // zero-terminated -> 10 bytes
178         i += 1;
179         if i == 10000 {
180             builder.reset();
181             i = 0;
182         }
183     });
184 
185     bench.bytes = 10;
186 }
187 
create_string_100(bench: &mut Bencher)188 fn create_string_100(bench: &mut Bencher) {
189     let builder = &mut flatbuffers::FlatBufferBuilder::with_capacity(1 << 20);
190     let s_owned = (0..99).map(|_| "x").collect::<String>();
191     let s: &str = &s_owned;
192 
193     let mut i = 0;
194     bench.iter(|| {
195         builder.create_string(s); // zero-terminated -> 100 bytes
196         i += 1;
197         if i == 1000 {
198             builder.reset();
199             i = 0;
200         }
201     });
202 
203     bench.bytes = s.len() as u64;
204 }
205 
create_byte_vector_100_naive(bench: &mut Bencher)206 fn create_byte_vector_100_naive(bench: &mut Bencher) {
207     let builder = &mut flatbuffers::FlatBufferBuilder::with_capacity(1 << 20);
208     let v_owned = (0u8..100).map(|i| i).collect::<Vec<u8>>();
209     let v: &[u8] = &v_owned;
210 
211     let mut i = 0;
212     bench.iter(|| {
213         builder.create_vector(v); // zero-terminated -> 100 bytes
214         i += 1;
215         if i == 10000 {
216             builder.reset();
217             i = 0;
218         }
219     });
220 
221     bench.bytes = v.len() as u64;
222 }
223 
create_byte_vector_100_optimal(bench: &mut Bencher)224 fn create_byte_vector_100_optimal(bench: &mut Bencher) {
225     let builder = &mut flatbuffers::FlatBufferBuilder::with_capacity(1 << 20);
226     let v_owned = (0u8..100).map(|i| i).collect::<Vec<u8>>();
227     let v: &[u8] = &v_owned;
228 
229     let mut i = 0;
230     bench.iter(|| {
231         builder.create_vector_direct(v);
232         i += 1;
233         if i == 10000 {
234             builder.reset();
235             i = 0;
236         }
237     });
238 
239     bench.bytes = v.len() as u64;
240 }
241 
create_many_tables(bench: &mut Bencher)242 fn create_many_tables(bench: &mut Bencher) {
243     let builder = &mut flatbuffers::FlatBufferBuilder::with_capacity(1 << 20);
244     // We test vtable overhead by making many unique tables of up to 16 fields of u8s.
245     bench.iter(|| {
246         for i in 0..(1u16 << 10) {
247             let t = builder.start_table();
248             for j in 0..15 {
249                 if i & (1 << j) == 1 {
250                     builder.push_slot_always(i * 2, 42u8);
251                 }
252             }
253             builder.end_table(t);
254         }
255         builder.reset();
256     });
257     bench.bytes = 1 << 15;
258 }
259 
260 benchmark_group!(
261     benches,
262     create_byte_vector_100_naive,
263     create_byte_vector_100_optimal,
264     traverse_canonical_buffer,
265     create_canonical_buffer_then_reset,
266     create_string_10,
267     create_string_100,
268     create_many_tables,
269 );
270