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 #[macro_use]
18 extern crate bencher;
19 use bencher::Bencher;
20 
21 extern crate flatbuffers;
22 
23 #[allow(dead_code, unused_imports)]
24 #[path = "../../monster_test_generated.rs"]
25 mod monster_test_generated;
26 pub use monster_test_generated::my_game;
27 
traverse_canonical_buffer(bench: &mut Bencher)28 fn traverse_canonical_buffer(bench: &mut Bencher) {
29     let owned_data = {
30         let mut builder = &mut flatbuffers::FlatBufferBuilder::new();
31         create_serialized_example_with_generated_code(&mut builder, true);
32         builder.finished_data().to_vec()
33     };
34     let data = &owned_data[..];
35     let n = data.len() as u64;
36     bench.iter(|| {
37         traverse_serialized_example_with_generated_code(data);
38     });
39     bench.bytes = n;
40 }
41 
create_canonical_buffer_then_reset(bench: &mut Bencher)42 fn create_canonical_buffer_then_reset(bench: &mut Bencher) {
43     let mut builder = &mut flatbuffers::FlatBufferBuilder::new();
44     // warmup
45     create_serialized_example_with_generated_code(&mut builder, true);
46     let n = builder.finished_data().len() as u64;
47     builder.reset();
48 
49     bench.iter(|| {
50         let _ = create_serialized_example_with_generated_code(&mut builder, true);
51         builder.reset();
52     });
53 
54     bench.bytes = n;
55 }
56 
57 #[inline(always)]
create_serialized_example_with_generated_code(builder: &mut flatbuffers::FlatBufferBuilder, finish: bool) -> usize58 fn create_serialized_example_with_generated_code(builder: &mut flatbuffers::FlatBufferBuilder, finish: bool) -> 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(builder, &my_game::example::MonsterArgs{
65         hp: 1000,
66         name: Some(t0_name),
67         ..Default::default()
68     });
69     let t1 = my_game::example::Monster::create(builder, &my_game::example::MonsterArgs{
70         name: Some(t1_name),
71         ..Default::default()
72     });
73     let t2 = my_game::example::Monster::create(builder, &my_game::example::MonsterArgs{
74         name: Some(t2_name),
75         ..Default::default()
76     });
77     let mon = {
78         let name = builder.create_string("MyMonster");
79         let fred_name = builder.create_string("Fred");
80         let inventory = builder.create_vector_direct(&[0u8, 1, 2, 3, 4]);
81         let test4 = builder.create_vector_direct(&[my_game::example::Test::new(10, 20),
82                                                    my_game::example::Test::new(30, 40)]);
83         let pos = my_game::example::Vec3::new(1.0, 2.0, 3.0, 3.0, my_game::example::Color::Green, &my_game::example::Test::new(5i16, 6i8));
84         let args = my_game::example::MonsterArgs{
85             hp: 80,
86             mana: 150,
87             name: Some(name),
88             pos: Some(&pos),
89             test_type: my_game::example::Any::Monster,
90             test: Some(my_game::example::Monster::create(builder, &my_game::example::MonsterArgs{
91                 name: Some(fred_name),
92                 ..Default::default()
93             }).as_union_value()),
94             inventory: Some(inventory),
95             test4: Some(test4),
96             testarrayofstring: Some(builder.create_vector(&[s0, s1])),
97             testarrayoftables: Some(builder.create_vector(&[t0, t1, t2])),
98             ..Default::default()
99         };
100         my_game::example::Monster::create(builder, &args)
101     };
102     if finish {
103         my_game::example::finish_monster_buffer(builder, mon);
104     }
105 
106     builder.finished_data().len()
107 
108     // make it do some work
109     // if builder.finished_data().len() == 0 { panic!("bad benchmark"); }
110 }
111 
112 #[inline(always)]
blackbox<T>(t: T) -> T113 fn blackbox<T>(t: T) -> T {
114     // encapsulate this in case we need to turn it into a noop
115     bencher::black_box(t)
116 }
117 
118 #[inline(always)]
traverse_serialized_example_with_generated_code(bytes: &[u8])119 fn traverse_serialized_example_with_generated_code(bytes: &[u8]) {
120     let m = my_game::example::get_root_as_monster(bytes);
121     blackbox(m.hp());
122     blackbox(m.mana());
123     blackbox(m.name());
124     let pos = m.pos().unwrap();
125     blackbox(pos.x());
126     blackbox(pos.y());
127     blackbox(pos.z());
128     blackbox(pos.test1());
129     blackbox(pos.test2());
130     let pos_test3 = pos.test3();
131     blackbox(pos_test3.a());
132     blackbox(pos_test3.b());
133     blackbox(m.test_type());
134     let table2 = m.test().unwrap();
135     let monster2 = my_game::example::Monster::init_from_table(table2);
136     blackbox(monster2.name());
137     blackbox(m.inventory());
138     blackbox(m.test4());
139     let testarrayoftables = m.testarrayoftables().unwrap();
140     blackbox(testarrayoftables.get(0).hp());
141     blackbox(testarrayoftables.get(0).name());
142     blackbox(testarrayoftables.get(1).name());
143     blackbox(testarrayoftables.get(2).name());
144     let testarrayofstring = m.testarrayofstring().unwrap();
145     blackbox(testarrayofstring.get(0));
146     blackbox(testarrayofstring.get(1));
147 }
148 
create_string_10(bench: &mut Bencher)149 fn create_string_10(bench: &mut Bencher) {
150     let builder = &mut flatbuffers::FlatBufferBuilder::new_with_capacity(1<<20);
151     let mut i = 0;
152     bench.iter(|| {
153         builder.create_string("foobarbaz"); // zero-terminated -> 10 bytes
154         i += 1;
155         if i == 10000 {
156             builder.reset();
157             i = 0;
158         }
159     });
160 
161     bench.bytes = 10;
162 }
163 
create_string_100(bench: &mut Bencher)164 fn create_string_100(bench: &mut Bencher) {
165     let builder = &mut flatbuffers::FlatBufferBuilder::new_with_capacity(1<<20);
166     let s_owned = (0..99).map(|_| "x").collect::<String>();
167     let s: &str = &s_owned;
168 
169     let mut i = 0;
170     bench.iter(|| {
171         builder.create_string(s); // zero-terminated -> 100 bytes
172         i += 1;
173         if i == 1000 {
174             builder.reset();
175             i = 0;
176         }
177     });
178 
179     bench.bytes = s.len() as u64;
180 }
181 
create_byte_vector_100_naive(bench: &mut Bencher)182 fn create_byte_vector_100_naive(bench: &mut Bencher) {
183     let builder = &mut flatbuffers::FlatBufferBuilder::new_with_capacity(1<<20);
184     let v_owned = (0u8..100).map(|i| i).collect::<Vec<u8>>();
185     let v: &[u8] = &v_owned;
186 
187     let mut i = 0;
188     bench.iter(|| {
189         builder.create_vector(v); // zero-terminated -> 100 bytes
190         i += 1;
191         if i == 10000 {
192             builder.reset();
193             i = 0;
194         }
195     });
196 
197     bench.bytes = v.len() as u64;
198 }
199 
create_byte_vector_100_optimal(bench: &mut Bencher)200 fn create_byte_vector_100_optimal(bench: &mut Bencher) {
201     let builder = &mut flatbuffers::FlatBufferBuilder::new_with_capacity(1<<20);
202     let v_owned = (0u8..100).map(|i| i).collect::<Vec<u8>>();
203     let v: &[u8] = &v_owned;
204 
205     let mut i = 0;
206     bench.iter(|| {
207         builder.create_vector_direct(v);
208         i += 1;
209         if i == 10000 {
210             builder.reset();
211             i = 0;
212         }
213     });
214 
215     bench.bytes = v.len() as u64;
216 }
217 
218 benchmark_group!(benches, create_byte_vector_100_naive, create_byte_vector_100_optimal, traverse_canonical_buffer, create_canonical_buffer_then_reset, create_string_10, create_string_100);
219 benchmark_main!(benches);
220