diff options
author | Derek Bailey <derekbailey@google.com> | 2021-11-15 13:41:22 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-15 13:41:22 -0800 |
commit | 0989fc5e59324590c542f1cf9b68c0a43a48c44a (patch) | |
tree | d9b4b608ccb4082fd8d1eaf810f9e8b1a5450feb | |
parent | 927175ea20929675f5985a05ad32fb346462c3e5 (diff) | |
download | flatbuffers-0989fc5e59324590c542f1cf9b68c0a43a48c44a.tar.gz flatbuffers-0989fc5e59324590c542f1cf9b68c0a43a48c44a.tar.bz2 flatbuffers-0989fc5e59324590c542f1cf9b68c0a43a48c44a.zip |
Added Google benchmarks (and gtests) (#6920)
* Added Google benchmarks (and gtests)
* Default building benchmarks to OFF as it requires c++11
* Separate benchmark CMakeLists.txt to its own file
* Move output directory to target just flatbenchmark
-rw-r--r-- | .gitignore | 4 | ||||
-rw-r--r-- | CMakeLists.txt | 8 | ||||
-rw-r--r-- | benchmarks/CMakeLists.txt | 81 | ||||
-rw-r--r-- | benchmarks/cpp/bench.h | 19 | ||||
-rw-r--r-- | benchmarks/cpp/benchmark_main.cpp | 61 | ||||
-rw-r--r-- | benchmarks/cpp/flatbuffers/bench.fbs | 52 | ||||
-rw-r--r-- | benchmarks/cpp/flatbuffers/bench_generated.h | 347 | ||||
-rw-r--r-- | benchmarks/cpp/flatbuffers/fb_bench.cpp | 81 | ||||
-rw-r--r-- | benchmarks/cpp/flatbuffers/fb_bench.h | 23 |
9 files changed, 676 insertions, 0 deletions
@@ -46,6 +46,8 @@ project.properties proguard-project.txt linklint_results Makefile +flatbenchmark +flatbenchmark.exe flatc flatc.exe flathash @@ -143,3 +145,5 @@ flatbuffers.pc **/FlatBuffers.Test.Swift.xcodeproj **/html/** **/latex/** +# https://cmake.org/cmake/help/latest/module/FetchContent.html#variable:FETCHCONTENT_BASE_DIR +_deps/
\ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 44d72c24..e53a3d8e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,9 @@ option(FLATBUFFERS_BUILD_FLATC "Enable the build of the flatbuffers compiler" option(FLATBUFFERS_STATIC_FLATC "Build flatbuffers compiler with -static flag" OFF) option(FLATBUFFERS_BUILD_FLATHASH "Enable the build of flathash" ON) +option(FLATBUFFERS_BUILD_BENCHMARKS "Enable the build of flatbenchmark. \" + Requires C++11." + OFF) option(FLATBUFFERS_BUILD_GRPCTEST "Enable the build of grpctest" OFF) option(FLATBUFFERS_BUILD_SHAREDLIB "Enable the build of the flatbuffers shared library" @@ -715,3 +718,8 @@ if(UNIX) include(CPack) endif() endif() + +# Include for running Google Benchmarks. +if(FLATBUFFERS_BUILD_BENCHMARKS AND CMAKE_VERSION VERSION_GREATER 3.13) + add_subdirectory(benchmarks) +endif()
\ No newline at end of file diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt new file mode 100644 index 00000000..d20464b3 --- /dev/null +++ b/benchmarks/CMakeLists.txt @@ -0,0 +1,81 @@ +# Setup for running Google Benchmarks (https://github.com/google/benchmark) on +# flatbuffers. This requires both that benchmark library and its depenency gtest +# to build. Instead of including them here or doing a submodule, this uses +# FetchContent (https://cmake.org/cmake/help/latest/module/FetchContent.html) to +# grab the dependencies at config time. This requires CMake 3.14 or higher. +cmake_minimum_required(VERSION 3.14) +include(FetchContent) + +# No particular reason for the specific GIT_TAGs for the following repos, they +# were just the latest releases when this was added. +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG e2239ee6043f73722e7aa812a459f54a28552929 # release-1.11.0 +) +FetchContent_Declare( + googlebenchmark + GIT_REPOSITORY https://github.com/google/benchmark.git + GIT_TAG f91b6b42b1b9854772a90ae9501464a161707d1e # v1.6.0 +) + +# For Windows: Prevent overriding the parent project's compiler/linker +# settings. +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable( + googletest + googlebenchmark +) + +set(CPP_BENCH_DIR cpp) +set(CPP_FB_BENCH_DIR ${CPP_BENCH_DIR}/flatbuffers) +set(CPP_BENCH_FBS ${CPP_FB_BENCH_DIR}/bench.fbs) +set(CPP_BENCH_FB_GEN ${CPP_FB_BENCH_DIR}/bench_generated.h) + +set(FlatBenchmark_SRCS + ${CPP_BENCH_DIR}/benchmark_main.cpp + ${CPP_BENCH_DIR}/bench.h + ${CPP_FB_BENCH_DIR}/fb_bench.cpp + ${CPP_FB_BENCH_DIR}/fb_bench.h + ${CPP_BENCH_FB_GEN} +) + +# Generate the flatbuffers benchmark code from the flatbuffers schema using +# flatc itself, thus it depends on flatc. This also depends on the C++ runtime +# flatbuffers and the schema file itself, so it should auto-generated at the +# correct times. +add_custom_command( + OUTPUT ${CPP_BENCH_FB_GEN} + COMMAND + "${FLATBUFFERS_FLATC_EXECUTABLE}" + --cpp + -o ${CPP_FB_BENCH_DIR} + ${CPP_BENCH_FBS} + DEPENDS + flatc + flatbuffers + ${CPP_BENCH_FBS} + COMMENT "Run Flatbuffers Benchmark Codegen: ${CPP_BENCH_FB_GEN}" + VERBATIM) + +# The main flatbuffers benchmark executable +add_executable(flatbenchmark ${FlatBenchmark_SRCS}) + +# Benchmark requires C++11 +target_compile_features(flatbenchmark PUBLIC + cxx_std_11 +) + +# Set the output directory to the root binary directory +set_target_properties(flatbenchmark + PROPERTIES RUNTIME_OUTPUT_DIRECTORY + "${CMAKE_BINARY_DIR}" +) + +# The includes of the benchmark files are fully qualified from flatbuffers root. +target_include_directories(flatbenchmark PUBLIC ${CMAKE_SOURCE_DIR}) + +target_link_libraries(flatbenchmark + benchmark::benchmark_main # _main to use their entry point + gtest # Link to gtest so we can also assert in the benchmarks +)
\ No newline at end of file diff --git a/benchmarks/cpp/bench.h b/benchmarks/cpp/bench.h new file mode 100644 index 00000000..ad4baebf --- /dev/null +++ b/benchmarks/cpp/bench.h @@ -0,0 +1,19 @@ +#ifndef BENCHMARKS_CPP_BENCH_H_ +#define BENCHMARKS_CPP_BENCH_H_ + +#include <cstdint> + +struct Bench { + virtual ~Bench() {} + + inline void Add(int64_t value) { sum += value; } + + virtual uint8_t *Encode(void *buf, int64_t &len) = 0; + virtual void *Decode(void *buf, int64_t len) = 0; + virtual int64_t Use(void *decoded) = 0; + virtual void Dealloc(void *decoded) = 0; + + int64_t sum = 0; +}; + +#endif // BENCHMARKS_CPP_BENCH_H_
\ No newline at end of file diff --git a/benchmarks/cpp/benchmark_main.cpp b/benchmarks/cpp/benchmark_main.cpp new file mode 100644 index 00000000..8ace5ac4 --- /dev/null +++ b/benchmarks/cpp/benchmark_main.cpp @@ -0,0 +1,61 @@ +#include <benchmark/benchmark.h> +#include <gtest/gtest.h> + +#include "benchmarks/cpp/bench.h" +#include "benchmarks/cpp/flatbuffers/fb_bench.h" + +static void BM_Flatbuffers_Encode(benchmark::State &state) { + const int64_t kBufferLength = 1024; + uint8_t buffer[kBufferLength]; + + int64_t length; + + StaticAllocator allocator(&buffer[0]); + std::unique_ptr<Bench> bench = NewFlatBuffersBench(kBufferLength, &allocator); + + for (auto _ : state) { + bench->Encode(buffer, length); + benchmark::DoNotOptimize(length); + } +} +BENCHMARK(BM_Flatbuffers_Encode); + +static void BM_Flatbuffers_Decode(benchmark::State &state) { + const int64_t kBufferLength = 1024; + uint8_t buffer[kBufferLength]; + + int64_t length; + + StaticAllocator allocator(&buffer[0]); + std::unique_ptr<Bench> bench = NewFlatBuffersBench(kBufferLength, &allocator); + + uint8_t* encoded = bench->Encode(buffer, length); + + for (auto _ : state) { + void* decoded = bench->Decode(encoded, length); + benchmark::DoNotOptimize(decoded); + } +} +BENCHMARK(BM_Flatbuffers_Decode); + +static void BM_Flatbuffers_Use(benchmark::State &state) { + const int64_t kBufferLength = 1024; + uint8_t buffer[kBufferLength]; + + int64_t length; + + StaticAllocator allocator(&buffer[0]); + std::unique_ptr<Bench> bench = NewFlatBuffersBench(kBufferLength, &allocator); + + uint8_t* encoded = bench->Encode(buffer, length); + void* decoded = bench->Decode(encoded, length); + + int64_t sum = 0; + + for (auto _ : state) { + sum = bench->Use(decoded); + } + + EXPECT_EQ(sum , 218812692406581874); +} +BENCHMARK(BM_Flatbuffers_Use);
\ No newline at end of file diff --git a/benchmarks/cpp/flatbuffers/bench.fbs b/benchmarks/cpp/flatbuffers/bench.fbs new file mode 100644 index 00000000..8e5f3ff7 --- /dev/null +++ b/benchmarks/cpp/flatbuffers/bench.fbs @@ -0,0 +1,52 @@ +// Copyright 2021 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +// trying to represent a typical mix of datatypes: +// 1 array of 3 elements, each element: 1 string, 3 nested objects, 9 scalars +// root element has the array, additional string and an enum + +namespace benchmarks_flatbuffers; + +enum Enum : short { Apples, Pears, Bananas} + +struct Foo { + id:ulong; + count:short; + prefix:byte; + length:uint; +} + +struct Bar { + parent:Foo; + time:int; + ratio:float; + size:ushort; +} + +table FooBar { + sibling:Bar; + name:string; + rating:double; + postfix:ubyte; +} + +table FooBarContainer { + list:[FooBar]; // 3 copies of the above + initialized:bool; + fruit:Enum; + location:string; +} + +root_type FooBarContainer; diff --git a/benchmarks/cpp/flatbuffers/bench_generated.h b/benchmarks/cpp/flatbuffers/bench_generated.h new file mode 100644 index 00000000..9d207c59 --- /dev/null +++ b/benchmarks/cpp/flatbuffers/bench_generated.h @@ -0,0 +1,347 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +#ifndef FLATBUFFERS_GENERATED_BENCH_BENCHMARKS_FLATBUFFERS_H_ +#define FLATBUFFERS_GENERATED_BENCH_BENCHMARKS_FLATBUFFERS_H_ + +#include "flatbuffers/flatbuffers.h" + +namespace benchmarks_flatbuffers { + +struct Foo; + +struct Bar; + +struct FooBar; +struct FooBarBuilder; + +struct FooBarContainer; +struct FooBarContainerBuilder; + +enum Enum : int16_t { + Enum_Apples = 0, + Enum_Pears = 1, + Enum_Bananas = 2, + Enum_MIN = Enum_Apples, + Enum_MAX = Enum_Bananas +}; + +inline const Enum (&EnumValuesEnum())[3] { + static const Enum values[] = { + Enum_Apples, + Enum_Pears, + Enum_Bananas + }; + return values; +} + +inline const char * const *EnumNamesEnum() { + static const char * const names[4] = { + "Apples", + "Pears", + "Bananas", + nullptr + }; + return names; +} + +inline const char *EnumNameEnum(Enum e) { + if (flatbuffers::IsOutRange(e, Enum_Apples, Enum_Bananas)) return ""; + const size_t index = static_cast<size_t>(e); + return EnumNamesEnum()[index]; +} + +FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Foo FLATBUFFERS_FINAL_CLASS { + private: + uint64_t id_; + int16_t count_; + int8_t prefix_; + int8_t padding0__; + uint32_t length_; + + public: + Foo() + : id_(0), + count_(0), + prefix_(0), + padding0__(0), + length_(0) { + (void)padding0__; + } + Foo(uint64_t _id, int16_t _count, int8_t _prefix, uint32_t _length) + : id_(flatbuffers::EndianScalar(_id)), + count_(flatbuffers::EndianScalar(_count)), + prefix_(flatbuffers::EndianScalar(_prefix)), + padding0__(0), + length_(flatbuffers::EndianScalar(_length)) { + (void)padding0__; + } + uint64_t id() const { + return flatbuffers::EndianScalar(id_); + } + int16_t count() const { + return flatbuffers::EndianScalar(count_); + } + int8_t prefix() const { + return flatbuffers::EndianScalar(prefix_); + } + uint32_t length() const { + return flatbuffers::EndianScalar(length_); + } +}; +FLATBUFFERS_STRUCT_END(Foo, 16); + +FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Bar FLATBUFFERS_FINAL_CLASS { + private: + benchmarks_flatbuffers::Foo parent_; + int32_t time_; + float ratio_; + uint16_t size_; + int16_t padding0__; int32_t padding1__; + + public: + Bar() + : parent_(), + time_(0), + ratio_(0), + size_(0), + padding0__(0), + padding1__(0) { + (void)padding0__; + (void)padding1__; + } + Bar(const benchmarks_flatbuffers::Foo &_parent, int32_t _time, float _ratio, uint16_t _size) + : parent_(_parent), + time_(flatbuffers::EndianScalar(_time)), + ratio_(flatbuffers::EndianScalar(_ratio)), + size_(flatbuffers::EndianScalar(_size)), + padding0__(0), + padding1__(0) { + (void)padding0__; + (void)padding1__; + } + const benchmarks_flatbuffers::Foo &parent() const { + return parent_; + } + int32_t time() const { + return flatbuffers::EndianScalar(time_); + } + float ratio() const { + return flatbuffers::EndianScalar(ratio_); + } + uint16_t size() const { + return flatbuffers::EndianScalar(size_); + } +}; +FLATBUFFERS_STRUCT_END(Bar, 32); + +struct FooBar FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef FooBarBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_SIBLING = 4, + VT_NAME = 6, + VT_RATING = 8, + VT_POSTFIX = 10 + }; + const benchmarks_flatbuffers::Bar *sibling() const { + return GetStruct<const benchmarks_flatbuffers::Bar *>(VT_SIBLING); + } + const flatbuffers::String *name() const { + return GetPointer<const flatbuffers::String *>(VT_NAME); + } + double rating() const { + return GetField<double>(VT_RATING, 0.0); + } + uint8_t postfix() const { + return GetField<uint8_t>(VT_POSTFIX, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField<benchmarks_flatbuffers::Bar>(verifier, VT_SIBLING) && + VerifyOffset(verifier, VT_NAME) && + verifier.VerifyString(name()) && + VerifyField<double>(verifier, VT_RATING) && + VerifyField<uint8_t>(verifier, VT_POSTFIX) && + verifier.EndTable(); + } +}; + +struct FooBarBuilder { + typedef FooBar Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_sibling(const benchmarks_flatbuffers::Bar *sibling) { + fbb_.AddStruct(FooBar::VT_SIBLING, sibling); + } + void add_name(flatbuffers::Offset<flatbuffers::String> name) { + fbb_.AddOffset(FooBar::VT_NAME, name); + } + void add_rating(double rating) { + fbb_.AddElement<double>(FooBar::VT_RATING, rating, 0.0); + } + void add_postfix(uint8_t postfix) { + fbb_.AddElement<uint8_t>(FooBar::VT_POSTFIX, postfix, 0); + } + explicit FooBarBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset<FooBar> Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset<FooBar>(end); + return o; + } +}; + +inline flatbuffers::Offset<FooBar> CreateFooBar( + flatbuffers::FlatBufferBuilder &_fbb, + const benchmarks_flatbuffers::Bar *sibling = nullptr, + flatbuffers::Offset<flatbuffers::String> name = 0, + double rating = 0.0, + uint8_t postfix = 0) { + FooBarBuilder builder_(_fbb); + builder_.add_rating(rating); + builder_.add_name(name); + builder_.add_sibling(sibling); + builder_.add_postfix(postfix); + return builder_.Finish(); +} + +inline flatbuffers::Offset<FooBar> CreateFooBarDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const benchmarks_flatbuffers::Bar *sibling = nullptr, + const char *name = nullptr, + double rating = 0.0, + uint8_t postfix = 0) { + auto name__ = name ? _fbb.CreateString(name) : 0; + return benchmarks_flatbuffers::CreateFooBar( + _fbb, + sibling, + name__, + rating, + postfix); +} + +struct FooBarContainer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef FooBarContainerBuilder Builder; + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_LIST = 4, + VT_INITIALIZED = 6, + VT_FRUIT = 8, + VT_LOCATION = 10 + }; + const flatbuffers::Vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>> *list() const { + return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>> *>(VT_LIST); + } + bool initialized() const { + return GetField<uint8_t>(VT_INITIALIZED, 0) != 0; + } + benchmarks_flatbuffers::Enum fruit() const { + return static_cast<benchmarks_flatbuffers::Enum>(GetField<int16_t>(VT_FRUIT, 0)); + } + const flatbuffers::String *location() const { + return GetPointer<const flatbuffers::String *>(VT_LOCATION); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_LIST) && + verifier.VerifyVector(list()) && + verifier.VerifyVectorOfTables(list()) && + VerifyField<uint8_t>(verifier, VT_INITIALIZED) && + VerifyField<int16_t>(verifier, VT_FRUIT) && + VerifyOffset(verifier, VT_LOCATION) && + verifier.VerifyString(location()) && + verifier.EndTable(); + } +}; + +struct FooBarContainerBuilder { + typedef FooBarContainer Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_list(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>> list) { + fbb_.AddOffset(FooBarContainer::VT_LIST, list); + } + void add_initialized(bool initialized) { + fbb_.AddElement<uint8_t>(FooBarContainer::VT_INITIALIZED, static_cast<uint8_t>(initialized), 0); + } + void add_fruit(benchmarks_flatbuffers::Enum fruit) { + fbb_.AddElement<int16_t>(FooBarContainer::VT_FRUIT, static_cast<int16_t>(fruit), 0); + } + void add_location(flatbuffers::Offset<flatbuffers::String> location) { + fbb_.AddOffset(FooBarContainer::VT_LOCATION, location); + } + explicit FooBarContainerBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset<FooBarContainer> Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset<FooBarContainer>(end); + return o; + } +}; + +inline flatbuffers::Offset<FooBarContainer> CreateFooBarContainer( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>> list = 0, + bool initialized = false, + benchmarks_flatbuffers::Enum fruit = benchmarks_flatbuffers::Enum_Apples, + flatbuffers::Offset<flatbuffers::String> location = 0) { + FooBarContainerBuilder builder_(_fbb); + builder_.add_location(location); + builder_.add_list(list); + builder_.add_fruit(fruit); + builder_.add_initialized(initialized); + return builder_.Finish(); +} + +inline flatbuffers::Offset<FooBarContainer> CreateFooBarContainerDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const std::vector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>> *list = nullptr, + bool initialized = false, + benchmarks_flatbuffers::Enum fruit = benchmarks_flatbuffers::Enum_Apples, + const char *location = nullptr) { + auto list__ = list ? _fbb.CreateVector<flatbuffers::Offset<benchmarks_flatbuffers::FooBar>>(*list) : 0; + auto location__ = location ? _fbb.CreateString(location) : 0; + return benchmarks_flatbuffers::CreateFooBarContainer( + _fbb, + list__, + initialized, + fruit, + location__); +} + +inline const benchmarks_flatbuffers::FooBarContainer *GetFooBarContainer(const void *buf) { + return flatbuffers::GetRoot<benchmarks_flatbuffers::FooBarContainer>(buf); +} + +inline const benchmarks_flatbuffers::FooBarContainer *GetSizePrefixedFooBarContainer(const void *buf) { + return flatbuffers::GetSizePrefixedRoot<benchmarks_flatbuffers::FooBarContainer>(buf); +} + +inline bool VerifyFooBarContainerBuffer( + flatbuffers::Verifier &verifier) { + return verifier.VerifyBuffer<benchmarks_flatbuffers::FooBarContainer>(nullptr); +} + +inline bool VerifySizePrefixedFooBarContainerBuffer( + flatbuffers::Verifier &verifier) { + return verifier.VerifySizePrefixedBuffer<benchmarks_flatbuffers::FooBarContainer>(nullptr); +} + +inline void FinishFooBarContainerBuffer( + flatbuffers::FlatBufferBuilder &fbb, + flatbuffers::Offset<benchmarks_flatbuffers::FooBarContainer> root) { + fbb.Finish(root); +} + +inline void FinishSizePrefixedFooBarContainerBuffer( + flatbuffers::FlatBufferBuilder &fbb, + flatbuffers::Offset<benchmarks_flatbuffers::FooBarContainer> root) { + fbb.FinishSizePrefixed(root); +} + +} // namespace benchmarks_flatbuffers + +#endif // FLATBUFFERS_GENERATED_BENCH_BENCHMARKS_FLATBUFFERS_H_ diff --git a/benchmarks/cpp/flatbuffers/fb_bench.cpp b/benchmarks/cpp/flatbuffers/fb_bench.cpp new file mode 100644 index 00000000..08dc0df7 --- /dev/null +++ b/benchmarks/cpp/flatbuffers/fb_bench.cpp @@ -0,0 +1,81 @@ +#include "benchmarks/cpp/flatbuffers/fb_bench.h" + +#include <cstdint> +#include <memory> + +#include "benchmarks/cpp/bench.h" +#include "benchmarks/cpp/flatbuffers/bench_generated.h" +#include "flatbuffers/flatbuffers.h" + +using namespace flatbuffers; +using namespace benchmarks_flatbuffers; + +namespace { + +struct FlatBufferBench : Bench { + explicit FlatBufferBench(int64_t initial_size, + Allocator *allocator) + : fbb(initial_size, allocator, false) {} + + uint8_t *Encode(void *, int64_t &len) override { + fbb.Clear(); + + const int kVectorLength = 3; + Offset<FooBar> vec[kVectorLength]; + + for(int i = 0; i < kVectorLength; ++i) { + Foo foo(0xABADCAFEABADCAFE + i, 10000 + i, '@' + i, 1000000 + i); + Bar bar(foo, 123456 + i, 3.14159f + i, 10000 + i); + auto name = fbb.CreateString("Hello, World!"); + auto foobar = CreateFooBar(fbb, &bar, name, 3.1415432432445543543 + i, + '!' + i); + vec[i] = foobar; + } + auto location = fbb.CreateString("http://google.com/flatbuffers/"); + auto foobarvec = fbb.CreateVector(vec, kVectorLength); + auto foobarcontainer = CreateFooBarContainer(fbb, foobarvec, true, + Enum_Bananas, location); + fbb.Finish(foobarcontainer); + + len = fbb.GetSize(); + return fbb.GetBufferPointer(); + } + + int64_t Use(void *decoded) override { + sum = 0; + auto foobarcontainer = GetFooBarContainer(decoded); + sum = 0; + Add(foobarcontainer->initialized()); + Add(foobarcontainer->location()->Length()); + Add(foobarcontainer->fruit()); + for (unsigned int i = 0; i < foobarcontainer->list()->Length(); i++) { + auto foobar = foobarcontainer->list()->Get(i); + Add(foobar->name()->Length()); + Add(foobar->postfix()); + Add(static_cast<int64_t>(foobar->rating())); + auto bar = foobar->sibling(); + Add(static_cast<int64_t>(bar->ratio())); + Add(bar->size()); + Add(bar->time()); + auto &foo = bar->parent(); + Add(foo.count()); + Add(foo.id()); + Add(foo.length()); + Add(foo.prefix()); + } + return sum; + } + + void *Decode(void *buffer, int64_t) override { return buffer; } + void Dealloc(void *) override{}; + + FlatBufferBuilder fbb; +}; + +} // namespace + +std::unique_ptr<Bench> NewFlatBuffersBench(int64_t initial_size, + Allocator *allocator) { + return std::unique_ptr<FlatBufferBench>( + new FlatBufferBench(initial_size, allocator)); +} diff --git a/benchmarks/cpp/flatbuffers/fb_bench.h b/benchmarks/cpp/flatbuffers/fb_bench.h new file mode 100644 index 00000000..ffb5f54c --- /dev/null +++ b/benchmarks/cpp/flatbuffers/fb_bench.h @@ -0,0 +1,23 @@ +#ifndef BENCHMARKS_CPP_FLATBUFFERS_FB_BENCH_H_ +#define BENCHMARKS_CPP_FLATBUFFERS_FB_BENCH_H_ + +#include <cstdint> +#include <memory> + +#include "benchmarks/cpp/bench.h" +#include "include/flatbuffers/flatbuffers.h" + +struct StaticAllocator : public flatbuffers::Allocator { + explicit StaticAllocator(uint8_t *buffer) : buffer_(buffer) {} + + uint8_t *allocate(size_t) override { return buffer_; } + + void deallocate(uint8_t *, size_t) override {} + + uint8_t *buffer_; +}; + +std::unique_ptr<Bench> NewFlatBuffersBench( + int64_t initial_size = 1024, flatbuffers::Allocator *allocator = nullptr); + +#endif // BENCHMARKS_CPP_FLATBUFFERS_FB_BENCH_H_
\ No newline at end of file |