1// Protocol Buffers - Google's data interchange format 2// Copyright 2008 Google Inc. All rights reserved. 3// https://developers.google.com/protocol-buffers/ 4// 5// Redistribution and use in source and binary forms, with or without 6// modification, are permitted provided that the following conditions are 7// met: 8// 9// * Redistributions of source code must retain the above copyright 10// notice, this list of conditions and the following disclaimer. 11// * Redistributions in binary form must reproduce the above 12// copyright notice, this list of conditions and the following disclaimer 13// in the documentation and/or other materials provided with the 14// distribution. 15// * Neither the name of Google Inc. nor the names of its 16// contributors may be used to endorse or promote products derived from 17// this software without specific prior written permission. 18// 19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31#include <fstream> 32#include <iostream> 33#include "benchmark/benchmark.h" 34#include "benchmarks.pb.h" 35#include "datasets/google_message1/proto2/benchmark_message1_proto2.pb.h" 36#include "datasets/google_message1/proto3/benchmark_message1_proto3.pb.h" 37#include "datasets/google_message2/benchmark_message2.pb.h" 38#include "datasets/google_message3/benchmark_message3.pb.h" 39#include "datasets/google_message4/benchmark_message4.pb.h" 40 41 42#define PREFIX "dataset." 43#define SUFFIX ".pb" 44 45using benchmarks::BenchmarkDataset; 46using google::protobuf::Arena; 47using google::protobuf::Descriptor; 48using google::protobuf::DescriptorPool; 49using google::protobuf::Message; 50using google::protobuf::MessageFactory; 51 52class Fixture : public benchmark::Fixture { 53 public: 54 Fixture(const BenchmarkDataset& dataset, const std::string& suffix) { 55 for (int i = 0; i < dataset.payload_size(); i++) { 56 payloads_.push_back(dataset.payload(i)); 57 } 58 59 const Descriptor* d = 60 DescriptorPool::generated_pool()->FindMessageTypeByName( 61 dataset.message_name()); 62 63 if (!d) { 64 std::cerr << "Couldn't find message named '" << dataset.message_name() 65 << "\n"; 66 } 67 68 prototype_ = MessageFactory::generated_factory()->GetPrototype(d); 69 SetName((dataset.name() + suffix).c_str()); 70 } 71 72 protected: 73 std::vector<std::string> payloads_; 74 const Message* prototype_; 75}; 76 77class WrappingCounter { 78 public: 79 WrappingCounter(size_t limit) : value_(0), limit_(limit) {} 80 81 size_t Next() { 82 size_t ret = value_; 83 if (++value_ == limit_) { 84 value_ = 0; 85 } 86 return ret; 87 } 88 89 private: 90 size_t value_; 91 size_t limit_; 92}; 93 94template <class T> 95class ParseNewFixture : public Fixture { 96 public: 97 ParseNewFixture(const BenchmarkDataset& dataset) 98 : Fixture(dataset, "_parse_new") {} 99 100 virtual void BenchmarkCase(benchmark::State& state) { 101 WrappingCounter i(payloads_.size()); 102 size_t total = 0; 103 104 while (state.KeepRunning()) { 105 T m; 106 const std::string& payload = payloads_[i.Next()]; 107 total += payload.size(); 108 m.ParseFromString(payload); 109 } 110 111 state.SetBytesProcessed(total); 112 } 113}; 114 115template <class T> 116class ParseNewArenaFixture : public Fixture { 117 public: 118 ParseNewArenaFixture(const BenchmarkDataset& dataset) 119 : Fixture(dataset, "_parse_newarena") {} 120 121 virtual void BenchmarkCase(benchmark::State& state) { 122 WrappingCounter i(payloads_.size()); 123 size_t total = 0; 124 Arena arena; 125 126 while (state.KeepRunning()) { 127 arena.Reset(); 128 Message* m = Arena::CreateMessage<T>(&arena); 129 const std::string& payload = payloads_[i.Next()]; 130 total += payload.size(); 131 m->ParseFromString(payload); 132 } 133 134 state.SetBytesProcessed(total); 135 } 136}; 137 138template <class T> 139class ParseReuseFixture : public Fixture { 140 public: 141 ParseReuseFixture(const BenchmarkDataset& dataset) 142 : Fixture(dataset, "_parse_reuse") {} 143 144 virtual void BenchmarkCase(benchmark::State& state) { 145 T m; 146 WrappingCounter i(payloads_.size()); 147 size_t total = 0; 148 149 while (state.KeepRunning()) { 150 const std::string& payload = payloads_[i.Next()]; 151 total += payload.size(); 152 m.ParseFromString(payload); 153 } 154 155 state.SetBytesProcessed(total); 156 } 157}; 158 159template <class T> 160class SerializeFixture : public Fixture { 161 public: 162 SerializeFixture(const BenchmarkDataset& dataset) 163 : Fixture(dataset, "_serialize") { 164 for (size_t i = 0; i < payloads_.size(); i++) { 165 message_.push_back(new T); 166 message_.back()->ParseFromString(payloads_[i]); 167 } 168 } 169 170 ~SerializeFixture() { 171 for (size_t i = 0; i < message_.size(); i++) { 172 delete message_[i]; 173 } 174 } 175 176 virtual void BenchmarkCase(benchmark::State& state) { 177 size_t total = 0; 178 std::string str; 179 WrappingCounter i(payloads_.size()); 180 181 while (state.KeepRunning()) { 182 str.clear(); 183 message_[i.Next()]->SerializeToString(&str); 184 total += str.size(); 185 } 186 187 state.SetBytesProcessed(total); 188 } 189 190 private: 191 std::vector<T*> message_; 192}; 193 194std::string ReadFile(const std::string& name) { 195 std::ifstream file(name.c_str()); 196 GOOGLE_CHECK(file.is_open()) << "Couldn't find file '" << name << 197 "', please make sure you are running " 198 "this command from the benchmarks/ " 199 "directory.\n"; 200 return std::string((std::istreambuf_iterator<char>(file)), 201 std::istreambuf_iterator<char>()); 202} 203 204template <class T> 205void RegisterBenchmarksForType(const BenchmarkDataset& dataset) { 206 ::benchmark::internal::RegisterBenchmarkInternal( 207 new ParseNewFixture<T>(dataset)); 208 ::benchmark::internal::RegisterBenchmarkInternal( 209 new ParseReuseFixture<T>(dataset)); 210 ::benchmark::internal::RegisterBenchmarkInternal( 211 new ParseNewArenaFixture<T>(dataset)); 212 ::benchmark::internal::RegisterBenchmarkInternal( 213 new SerializeFixture<T>(dataset)); 214} 215 216void RegisterBenchmarks(const std::string& dataset_bytes) { 217 BenchmarkDataset dataset; 218 GOOGLE_CHECK(dataset.ParseFromString(dataset_bytes)); 219 220 if (dataset.message_name() == "benchmarks.proto3.GoogleMessage1") { 221 RegisterBenchmarksForType<benchmarks::proto3::GoogleMessage1>(dataset); 222 } else if (dataset.message_name() == "benchmarks.proto2.GoogleMessage1") { 223 RegisterBenchmarksForType<benchmarks::proto2::GoogleMessage1>(dataset); 224 } else if (dataset.message_name() == "benchmarks.proto2.GoogleMessage2") { 225 RegisterBenchmarksForType<benchmarks::proto2::GoogleMessage2>(dataset); 226 } else if (dataset.message_name() == 227 "benchmarks.google_message3.GoogleMessage3") { 228 RegisterBenchmarksForType 229 <benchmarks::google_message3::GoogleMessage3>(dataset); 230 } else if (dataset.message_name() == 231 "benchmarks.google_message4.GoogleMessage4") { 232 RegisterBenchmarksForType 233 <benchmarks::google_message4::GoogleMessage4>(dataset); 234 } else { 235 std::cerr << "Unknown message type: " << dataset.message_name(); 236 exit(1); 237 } 238} 239 240int main(int argc, char *argv[]) { 241 ::benchmark::Initialize(&argc, argv); 242 if (argc == 1) { 243 std::cerr << "Usage: ./cpp-benchmark <input data>" << std::endl; 244 std::cerr << "input data is in the format of \"benchmarks.proto\"" 245 << std::endl; 246 return 1; 247 } else { 248 for (int i = 1; i < argc; i++) { 249 RegisterBenchmarks(ReadFile(argv[i])); 250 } 251 } 252 253 ::benchmark::RunSpecifiedBenchmarks(); 254} 255