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