diff options
author | Yilun Chong <chongyilun250@sina.com> | 2018-04-10 14:23:07 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-10 14:23:07 -0700 |
commit | 5fb73f80f29e2521e450af40acd6b762ff483026 (patch) | |
tree | 65b0a8a0cce04ca2d4a1ce13a4803513be14d358 /benchmarks/cpp/cpp_benchmark.cc | |
parent | d7d863ea077690954494fba168f5aba198a8f41c (diff) | |
parent | 805174eda2356df1b01752c8bc57019e696e0a75 (diff) | |
download | protobuf-5fb73f80f29e2521e450af40acd6b762ff483026.tar.gz protobuf-5fb73f80f29e2521e450af40acd6b762ff483026.tar.bz2 protobuf-5fb73f80f29e2521e450af40acd6b762ff483026.zip |
Merge pull request #4415 from BSBandme/experiement
Add dashboard support
Diffstat (limited to 'benchmarks/cpp/cpp_benchmark.cc')
-rw-r--r-- | benchmarks/cpp/cpp_benchmark.cc | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/benchmarks/cpp/cpp_benchmark.cc b/benchmarks/cpp/cpp_benchmark.cc new file mode 100644 index 00000000..f8b55291 --- /dev/null +++ b/benchmarks/cpp/cpp_benchmark.cc @@ -0,0 +1,254 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <fstream> +#include <iostream> +#include "benchmark/benchmark_api.h" +#include "benchmarks.pb.h" +#include "datasets/google_message1/proto2/benchmark_message1_proto2.pb.h" +#include "datasets/google_message1/proto3/benchmark_message1_proto3.pb.h" +#include "datasets/google_message2/benchmark_message2.pb.h" +#include "datasets/google_message3/benchmark_message3.pb.h" +#include "datasets/google_message4/benchmark_message4.pb.h" + + +#define PREFIX "dataset." +#define SUFFIX ".pb" + +using benchmarks::BenchmarkDataset; +using google::protobuf::Arena; +using google::protobuf::Descriptor; +using google::protobuf::DescriptorPool; +using google::protobuf::Message; +using google::protobuf::MessageFactory; + +class Fixture : public benchmark::Fixture { + public: + Fixture(const BenchmarkDataset& dataset, const std::string& suffix) { + for (int i = 0; i < dataset.payload_size(); i++) { + payloads_.push_back(dataset.payload(i)); + } + + const Descriptor* d = + DescriptorPool::generated_pool()->FindMessageTypeByName( + dataset.message_name()); + + if (!d) { + std::cerr << "Couldn't find message named '" << dataset.message_name() + << "\n"; + } + + prototype_ = MessageFactory::generated_factory()->GetPrototype(d); + SetName((dataset.name() + suffix).c_str()); + } + + protected: + std::vector<std::string> payloads_; + const Message* prototype_; +}; + +class WrappingCounter { + public: + WrappingCounter(size_t limit) : value_(0), limit_(limit) {} + + size_t Next() { + size_t ret = value_; + if (++value_ == limit_) { + value_ = 0; + } + return ret; + } + + private: + size_t value_; + size_t limit_; +}; + +template <class T> +class ParseNewFixture : public Fixture { + public: + ParseNewFixture(const BenchmarkDataset& dataset) + : Fixture(dataset, "_parse_new") {} + + virtual void BenchmarkCase(benchmark::State& state) { + WrappingCounter i(payloads_.size()); + size_t total = 0; + + while (state.KeepRunning()) { + T m; + const std::string& payload = payloads_[i.Next()]; + total += payload.size(); + m.ParseFromString(payload); + } + + state.SetBytesProcessed(total); + } +}; + +template <class T> +class ParseNewArenaFixture : public Fixture { + public: + ParseNewArenaFixture(const BenchmarkDataset& dataset) + : Fixture(dataset, "_parse_newarena") {} + + virtual void BenchmarkCase(benchmark::State& state) { + WrappingCounter i(payloads_.size()); + size_t total = 0; + Arena arena; + + while (state.KeepRunning()) { + arena.Reset(); + Message* m = Arena::CreateMessage<T>(&arena); + const std::string& payload = payloads_[i.Next()]; + total += payload.size(); + m->ParseFromString(payload); + } + + state.SetBytesProcessed(total); + } +}; + +template <class T> +class ParseReuseFixture : public Fixture { + public: + ParseReuseFixture(const BenchmarkDataset& dataset) + : Fixture(dataset, "_parse_reuse") {} + + virtual void BenchmarkCase(benchmark::State& state) { + T m; + WrappingCounter i(payloads_.size()); + size_t total = 0; + + while (state.KeepRunning()) { + const std::string& payload = payloads_[i.Next()]; + total += payload.size(); + m.ParseFromString(payload); + } + + state.SetBytesProcessed(total); + } +}; + +template <class T> +class SerializeFixture : public Fixture { + public: + SerializeFixture(const BenchmarkDataset& dataset) + : Fixture(dataset, "_serialize") { + for (size_t i = 0; i < payloads_.size(); i++) { + message_.push_back(new T); + message_.back()->ParseFromString(payloads_[i]); + } + } + + ~SerializeFixture() { + for (size_t i = 0; i < message_.size(); i++) { + delete message_[i]; + } + } + + virtual void BenchmarkCase(benchmark::State& state) { + size_t total = 0; + std::string str; + WrappingCounter i(payloads_.size()); + + while (state.KeepRunning()) { + str.clear(); + message_[i.Next()]->SerializeToString(&str); + total += str.size(); + } + + state.SetBytesProcessed(total); + } + + private: + std::vector<T*> message_; +}; + +std::string ReadFile(const std::string& name) { + std::ifstream file(name.c_str()); + GOOGLE_CHECK(file.is_open()) << "Couldn't find file '" << name << + "', please make sure you are running " + "this command from the benchmarks/ " + "directory.\n"; + return std::string((std::istreambuf_iterator<char>(file)), + std::istreambuf_iterator<char>()); +} + +template <class T> +void RegisterBenchmarksForType(const BenchmarkDataset& dataset) { + ::benchmark::internal::RegisterBenchmarkInternal( + new ParseNewFixture<T>(dataset)); + ::benchmark::internal::RegisterBenchmarkInternal( + new ParseReuseFixture<T>(dataset)); + ::benchmark::internal::RegisterBenchmarkInternal( + new ParseNewArenaFixture<T>(dataset)); + ::benchmark::internal::RegisterBenchmarkInternal( + new SerializeFixture<T>(dataset)); +} + +void RegisterBenchmarks(const std::string& dataset_bytes) { + BenchmarkDataset dataset; + GOOGLE_CHECK(dataset.ParseFromString(dataset_bytes)); + + if (dataset.message_name() == "benchmarks.proto3.GoogleMessage1") { + RegisterBenchmarksForType<benchmarks::proto3::GoogleMessage1>(dataset); + } else if (dataset.message_name() == "benchmarks.proto2.GoogleMessage1") { + RegisterBenchmarksForType<benchmarks::proto2::GoogleMessage1>(dataset); + } else if (dataset.message_name() == "benchmarks.proto2.GoogleMessage2") { + RegisterBenchmarksForType<benchmarks::proto2::GoogleMessage2>(dataset); + } else if (dataset.message_name() == + "benchmarks.google_message3.GoogleMessage3") { + RegisterBenchmarksForType + <benchmarks::google_message3::GoogleMessage3>(dataset); + } else if (dataset.message_name() == + "benchmarks.google_message4.GoogleMessage4") { + RegisterBenchmarksForType + <benchmarks::google_message4::GoogleMessage4>(dataset); + } else { + std::cerr << "Unknown message type: " << dataset.message_name(); + exit(1); + } +} + +int main(int argc, char *argv[]) { + ::benchmark::Initialize(&argc, argv); + if (argc == 1) { + std::cerr << "Usage: ./cpp-benchmark <input data>" << std::endl; + std::cerr << "input data is in the format of \"benchmarks.proto\"" + << std::endl; + return 1; + } else { + for (int i = 1; i < argc; i++) { + RegisterBenchmarks(ReadFile(argv[i])); + } + } + + ::benchmark::RunSpecifiedBenchmarks(); +} |