xref: /aosp_15_r20/external/flatbuffers/tests/rust_usage_test/benches/flexbuffers_benchmarks.rs (revision 890232f25432b36107d06881e0a25aaa6b473652)
1 // Copyright 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use bencher::{benchmark_group, benchmark_main, Bencher};
16 use flexbuffers::*;
17 
push_vec_u64_to_map(b: &mut Bencher)18 fn push_vec_u64_to_map(b: &mut Bencher) {
19     let va = vec![u64::max_value() - 10; 512];
20     let vb = vec![u64::max_value() - 20; 512];
21     let vc = vec![u64::max_value() - 30; 512];
22     let mut n = 0;
23 
24     b.iter(|| {
25         let mut fxb = Builder::default();
26         let mut m = fxb.start_map();
27         let mut ma = m.start_vector("a");
28         for &a in va.iter() {
29             ma.push(a);
30         }
31         ma.end_vector();
32         let mut mb = m.start_vector("b");
33         for &b in vb.iter() {
34             mb.push(b);
35         }
36         mb.end_vector();
37         let mut mc = m.start_vector("c");
38         for &c in vc.iter() {
39             mc.push(c);
40         }
41         mc.end_vector();
42         m.end_map();
43         n = fxb.view().len();
44     });
45     b.bytes = n as u64;
46 }
push_vec_u64_to_map_reused(b: &mut Bencher)47 fn push_vec_u64_to_map_reused(b: &mut Bencher) {
48     let va = vec![u64::max_value() - 10; 512];
49     let vb = vec![u64::max_value() - 20; 512];
50     let vc = vec![u64::max_value() - 30; 512];
51     let mut fxb = Builder::default();
52     let mut n = 0;
53     let mut go = || {
54         let mut m = fxb.start_map();
55         let mut ma = m.start_vector("a");
56         for &a in va.iter() {
57             ma.push(a);
58         }
59         ma.end_vector();
60         let mut mb = m.start_vector("b");
61         for &b in vb.iter() {
62             mb.push(b);
63         }
64         mb.end_vector();
65         let mut mc = m.start_vector("c");
66         for &c in vc.iter() {
67             mc.push(c);
68         }
69         mc.end_vector();
70         m.end_map();
71         n = fxb.view().len();
72     };
73     go(); // warm up allocations.
74     b.iter(go);
75     b.bytes = n as u64;
76 }
push_vec_u64_to_map_direct(b: &mut Bencher)77 fn push_vec_u64_to_map_direct(b: &mut Bencher) {
78     let va = vec![u64::max_value() - 10; 512];
79     let vb = vec![u64::max_value() - 20; 512];
80     let vc = vec![u64::max_value() - 30; 512];
81     let mut n = 0;
82 
83     b.iter(|| {
84         let mut fxb = Builder::default();
85         let mut m = fxb.start_map();
86         m.push("a", &va);
87         m.push("b", &vb);
88         m.push("c", &vc);
89         m.end_map();
90         n = fxb.view().len();
91     });
92     b.bytes = n as u64;
93 }
push_vec_u64_to_map_direct_reused(b: &mut Bencher)94 fn push_vec_u64_to_map_direct_reused(b: &mut Bencher) {
95     let va = vec![u64::max_value() - 10; 512];
96     let vb = vec![u64::max_value() - 20; 512];
97     let vc = vec![u64::max_value() - 30; 512];
98     let mut n = 0;
99     let mut fxb = Builder::default();
100     let mut go = || {
101         let mut m = fxb.start_map();
102         m.push("a", &va);
103         m.push("b", &vb);
104         m.push("c", &vc);
105         m.end_map();
106         n = fxb.view().len();
107     };
108     go(); // warm up allocations.
109     b.iter(go);
110     b.bytes = n as u64;
111 }
112 
push_vec_without_indirect(b: &mut Bencher)113 fn push_vec_without_indirect(b: &mut Bencher) {
114     let mut builder = Builder::default();
115     let mut n = 0;
116     let mut go = || {
117         let mut b = builder.start_vector();
118         for i in 0..1024u16 {
119             b.push(i);
120         }
121         b.push(i64::max_value());
122         b.end_vector();
123         n = builder.view().len();
124     };
125     go(); // warm up allocations.
126     b.iter(go);
127     b.bytes = n as u64;
128 }
129 // This isn't actually faster than the alternative but it is a lot smaller.
130 // Based on the above benchmarks a lot of time is stuck in the `values` stack.
push_vec_with_indirect(b: &mut Bencher)131 fn push_vec_with_indirect(b: &mut Bencher) {
132     let mut builder = Builder::default();
133     let mut n = 0;
134     let mut go = || {
135         let mut b = builder.start_vector();
136         for i in 0..1024u16 {
137             b.push(i);
138         }
139         b.push(IndirectInt(i64::max_value()));
140         b.end_vector();
141         n = builder.view().len();
142     };
143     go(); // warm up allocations.
144     b.iter(go);
145     b.bytes = n as u64;
146 }
147 
example_map<'a>(m: &mut MapBuilder<'a>)148 fn example_map<'a>(m: &mut MapBuilder<'a>) {
149     m.push("some_ints", &[256; 5]);
150     m.push("some_uints", &[256u16; 5]);
151     m.push("some_floats", &[256f32; 5]);
152     m.push("some_strings", "muahahahahaha");
153 }
hundred_maps(b: &mut Bencher)154 fn hundred_maps(b: &mut Bencher) {
155     let mut builder = Builder::default();
156     let mut n = 0;
157     let mut go = || {
158         let mut v = builder.start_vector();
159         for _ in 0..100 {
160             example_map(&mut v.start_map());
161         }
162         v.end_vector();
163         n = builder.view().len();
164     };
165     go(); // Warm up allocations.
166     b.iter(go);
167     b.bytes = n as u64;
168 }
hundred_maps_pooled(b: &mut Bencher)169 fn hundred_maps_pooled(b: &mut Bencher) {
170     let mut builder = Builder::default();
171     let mut n = 0;
172     let mut go = || {
173         let mut v = builder.start_vector();
174         for _ in 0..100 {
175             example_map(&mut v.start_map());
176         }
177         v.end_vector();
178         n = builder.view().len();
179     };
180     go(); // Warm up allocations.
181     b.iter(go);
182     b.bytes = n as u64;
183 }
make_monster(mut monster: MapBuilder)184 fn make_monster(mut monster: MapBuilder) {
185     monster.push("type", "great orc");
186     monster.push("age", 100u8);
187     monster.push("name", "Mr. Orc");
188     monster.push("coins", &[1, 25, 50, 100, 250]);
189     monster.push("color", &[255u8, 0, 0, 0]);
190     {
191         let mut weapons = monster.start_vector("weapons");
192         {
193             let mut hammer = weapons.start_map();
194             hammer.push("name", "hammer");
195             hammer.push("damage type", "crush");
196             hammer.push("damage", 20);
197         }
198         {
199             let mut axe = weapons.start_map();
200             axe.push("name", "Great Axe");
201             axe.push("damage type", "slash");
202             axe.push("damage", 30);
203         }
204     }
205     {
206         let mut sounds = monster.start_vector("sounds");
207         sounds.push("grr");
208         sounds.push("rawr");
209         sounds.push("muahaha");
210     }
211 }
serialize_monsters(b: &mut Bencher)212 fn serialize_monsters(b: &mut Bencher) {
213     let mut builder = Builder::default();
214     let mut n = 0;
215     let mut go = || {
216         let mut monsters = builder.start_vector();
217         for _ in 0..100 {
218             make_monster(monsters.start_map())
219         }
220         monsters.end_vector();
221         n = builder.view().len();
222     };
223     go(); // Warm up allocations.
224     b.iter(go);
225     b.bytes = n as u64;
226 }
validate_monster(r: MapReader<&[u8]>)227 fn validate_monster(r: MapReader<&[u8]>) {
228     assert_eq!(r.idx("type").as_str(), "great orc");
229     assert_eq!(r.idx("age").as_u8(), 100);
230     assert_eq!(r.idx("name").as_str(), "Mr. Orc");
231     assert!(r
232         .idx("coins")
233         .as_vector()
234         .iter()
235         .map(|c| c.as_i16())
236         .eq([1, 25, 50, 100, 250].iter().cloned()));
237     assert!(r
238         .idx("color")
239         .as_vector()
240         .iter()
241         .map(|c| c.as_u8())
242         .eq([255, 0, 0, 0].iter().cloned()));
243 
244     let weapons = r.idx("weapons").as_vector();
245     assert_eq!(weapons.len(), 2);
246 
247     let hammer = weapons.idx(0).as_map();
248     assert_eq!(hammer.idx("name").as_str(), "hammer");
249     assert_eq!(hammer.idx("damage type").as_str(), "crush");
250     assert_eq!(hammer.idx("damage").as_u64(), 20);
251 
252     let axe = weapons.idx(1).as_map();
253     assert_eq!(axe.idx("name").as_str(), "Great Axe");
254     assert_eq!(axe.idx("damage type").as_str(), "slash");
255     assert_eq!(axe.idx("damage").as_u64(), 30);
256 
257     assert!(r
258         .idx("sounds")
259         .as_vector()
260         .iter()
261         .map(|s| s.as_str())
262         .eq(["grr", "rawr", "muahaha"].iter().cloned()));
263 }
read_monsters(b: &mut Bencher)264 fn read_monsters(b: &mut Bencher) {
265     let mut builder = Builder::default();
266     let mut monsters = builder.start_vector();
267     for _ in 0..100 {
268         make_monster(monsters.start_map());
269     }
270     monsters.end_vector();
271     b.bytes = builder.view().len() as u64;
272     let go = || {
273         let r = Reader::get_root(builder.view()).unwrap().as_vector();
274         assert_eq!(r.len(), 100);
275         for i in 0..100 {
276             validate_monster(r.idx(i).as_map());
277         }
278     };
279     b.iter(go);
280 }
281 
282 benchmark_group!(
283     benches,
284     push_vec_u64_to_map,
285     push_vec_u64_to_map_reused,
286     push_vec_u64_to_map_direct,
287     push_vec_u64_to_map_direct_reused,
288     push_vec_without_indirect,
289     push_vec_with_indirect,
290     hundred_maps,
291     hundred_maps_pooled,
292     serialize_monsters,
293     read_monsters,
294 );
295 benchmark_main!(benches);
296