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