forked from BigfootDev/flatbuffers
Added Raw C++ benchmarks (#6924)
This commit is contained in:
@@ -29,15 +29,14 @@ FetchContent_MakeAvailable(
|
|||||||
|
|
||||||
set(CPP_BENCH_DIR cpp)
|
set(CPP_BENCH_DIR cpp)
|
||||||
set(CPP_FB_BENCH_DIR ${CPP_BENCH_DIR}/flatbuffers)
|
set(CPP_FB_BENCH_DIR ${CPP_BENCH_DIR}/flatbuffers)
|
||||||
|
set(CPP_RAW_BENCH_DIR ${CPP_BENCH_DIR}/raw)
|
||||||
set(CPP_BENCH_FBS ${CPP_FB_BENCH_DIR}/bench.fbs)
|
set(CPP_BENCH_FBS ${CPP_FB_BENCH_DIR}/bench.fbs)
|
||||||
set(CPP_BENCH_FB_GEN ${CPP_FB_BENCH_DIR}/bench_generated.h)
|
set(CPP_BENCH_FB_GEN ${CPP_FB_BENCH_DIR}/bench_generated.h)
|
||||||
|
|
||||||
set(FlatBenchmark_SRCS
|
set(FlatBenchmark_SRCS
|
||||||
${CPP_BENCH_DIR}/benchmark_main.cpp
|
${CPP_BENCH_DIR}/benchmark_main.cpp
|
||||||
${CPP_BENCH_DIR}/bench.h
|
|
||||||
${CPP_FB_BENCH_DIR}/fb_bench.cpp
|
${CPP_FB_BENCH_DIR}/fb_bench.cpp
|
||||||
${CPP_FB_BENCH_DIR}/fb_bench.h
|
${CPP_RAW_BENCH_DIR}/raw_bench.cpp
|
||||||
${CPP_BENCH_FB_GEN}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Generate the flatbuffers benchmark code from the flatbuffers schema using
|
# Generate the flatbuffers benchmark code from the flatbuffers schema using
|
||||||
|
|||||||
@@ -3,20 +3,48 @@
|
|||||||
|
|
||||||
#include "benchmarks/cpp/bench.h"
|
#include "benchmarks/cpp/bench.h"
|
||||||
#include "benchmarks/cpp/flatbuffers/fb_bench.h"
|
#include "benchmarks/cpp/flatbuffers/fb_bench.h"
|
||||||
|
#include "benchmarks/cpp/raw/raw_bench.h"
|
||||||
|
|
||||||
|
static inline void Encode(benchmark::State &state,
|
||||||
|
std::unique_ptr<Bench> &bench, uint8_t *buffer) {
|
||||||
|
int64_t length;
|
||||||
|
for (auto _ : state) {
|
||||||
|
bench->Encode(buffer, length);
|
||||||
|
benchmark::DoNotOptimize(length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void Decode(benchmark::State &state,
|
||||||
|
std::unique_ptr<Bench> &bench, uint8_t *buffer) {
|
||||||
|
int64_t length;
|
||||||
|
uint8_t *encoded = bench->Encode(buffer, length);
|
||||||
|
|
||||||
|
for (auto _ : state) {
|
||||||
|
void *decoded = bench->Decode(encoded, length);
|
||||||
|
benchmark::DoNotOptimize(decoded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void Use(benchmark::State &state, std::unique_ptr<Bench> &bench,
|
||||||
|
uint8_t *buffer, int64_t check_sum) {
|
||||||
|
int64_t length;
|
||||||
|
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, check_sum);
|
||||||
|
}
|
||||||
|
|
||||||
static void BM_Flatbuffers_Encode(benchmark::State &state) {
|
static void BM_Flatbuffers_Encode(benchmark::State &state) {
|
||||||
const int64_t kBufferLength = 1024;
|
const int64_t kBufferLength = 1024;
|
||||||
uint8_t buffer[kBufferLength];
|
uint8_t buffer[kBufferLength];
|
||||||
|
|
||||||
int64_t length;
|
|
||||||
|
|
||||||
StaticAllocator allocator(&buffer[0]);
|
StaticAllocator allocator(&buffer[0]);
|
||||||
std::unique_ptr<Bench> bench = NewFlatBuffersBench(kBufferLength, &allocator);
|
std::unique_ptr<Bench> bench = NewFlatBuffersBench(kBufferLength, &allocator);
|
||||||
|
Encode(state, bench, buffer);
|
||||||
for (auto _ : state) {
|
|
||||||
bench->Encode(buffer, length);
|
|
||||||
benchmark::DoNotOptimize(length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
BENCHMARK(BM_Flatbuffers_Encode);
|
BENCHMARK(BM_Flatbuffers_Encode);
|
||||||
|
|
||||||
@@ -24,17 +52,9 @@ static void BM_Flatbuffers_Decode(benchmark::State &state) {
|
|||||||
const int64_t kBufferLength = 1024;
|
const int64_t kBufferLength = 1024;
|
||||||
uint8_t buffer[kBufferLength];
|
uint8_t buffer[kBufferLength];
|
||||||
|
|
||||||
int64_t length;
|
|
||||||
|
|
||||||
StaticAllocator allocator(&buffer[0]);
|
StaticAllocator allocator(&buffer[0]);
|
||||||
std::unique_ptr<Bench> bench = NewFlatBuffersBench(kBufferLength, &allocator);
|
std::unique_ptr<Bench> bench = NewFlatBuffersBench(kBufferLength, &allocator);
|
||||||
|
Decode(state, bench, buffer);
|
||||||
uint8_t* encoded = bench->Encode(buffer, length);
|
|
||||||
|
|
||||||
for (auto _ : state) {
|
|
||||||
void* decoded = bench->Decode(encoded, length);
|
|
||||||
benchmark::DoNotOptimize(decoded);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
BENCHMARK(BM_Flatbuffers_Decode);
|
BENCHMARK(BM_Flatbuffers_Decode);
|
||||||
|
|
||||||
@@ -42,20 +62,35 @@ static void BM_Flatbuffers_Use(benchmark::State &state) {
|
|||||||
const int64_t kBufferLength = 1024;
|
const int64_t kBufferLength = 1024;
|
||||||
uint8_t buffer[kBufferLength];
|
uint8_t buffer[kBufferLength];
|
||||||
|
|
||||||
int64_t length;
|
|
||||||
|
|
||||||
StaticAllocator allocator(&buffer[0]);
|
StaticAllocator allocator(&buffer[0]);
|
||||||
std::unique_ptr<Bench> bench = NewFlatBuffersBench(kBufferLength, &allocator);
|
std::unique_ptr<Bench> bench = NewFlatBuffersBench(kBufferLength, &allocator);
|
||||||
|
Use(state, bench, buffer, 218812692406581874);
|
||||||
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);
|
BENCHMARK(BM_Flatbuffers_Use);
|
||||||
|
|
||||||
|
static void BM_Raw_Encode(benchmark::State &state) {
|
||||||
|
const int64_t kBufferLength = 1024;
|
||||||
|
uint8_t buffer[kBufferLength];
|
||||||
|
|
||||||
|
std::unique_ptr<Bench> bench = NewRawBench();
|
||||||
|
Encode(state, bench, buffer);
|
||||||
|
}
|
||||||
|
BENCHMARK(BM_Raw_Encode);
|
||||||
|
|
||||||
|
static void BM_Raw_Decode(benchmark::State &state) {
|
||||||
|
const int64_t kBufferLength = 1024;
|
||||||
|
uint8_t buffer[kBufferLength];
|
||||||
|
|
||||||
|
std::unique_ptr<Bench> bench = NewRawBench();
|
||||||
|
Decode(state, bench, buffer);
|
||||||
|
}
|
||||||
|
BENCHMARK(BM_Raw_Decode);
|
||||||
|
|
||||||
|
static void BM_Raw_Use(benchmark::State &state) {
|
||||||
|
const int64_t kBufferLength = 1024;
|
||||||
|
uint8_t buffer[kBufferLength];
|
||||||
|
|
||||||
|
std::unique_ptr<Bench> bench = NewRawBench();
|
||||||
|
Use(state, bench, buffer, 218812692406581874);
|
||||||
|
}
|
||||||
|
BENCHMARK(BM_Raw_Use);
|
||||||
@@ -13,35 +13,34 @@ using namespace benchmarks_flatbuffers;
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct FlatBufferBench : Bench {
|
struct FlatBufferBench : Bench {
|
||||||
explicit FlatBufferBench(int64_t initial_size,
|
explicit FlatBufferBench(int64_t initial_size, Allocator *allocator)
|
||||||
Allocator *allocator)
|
|
||||||
: fbb(initial_size, allocator, false) {}
|
: fbb(initial_size, allocator, false) {}
|
||||||
|
|
||||||
uint8_t *Encode(void *, int64_t &len) override {
|
uint8_t *Encode(void *, int64_t &len) {
|
||||||
fbb.Clear();
|
fbb.Clear();
|
||||||
|
|
||||||
const int kVectorLength = 3;
|
const int kVectorLength = 3;
|
||||||
Offset<FooBar> vec[kVectorLength];
|
Offset<FooBar> vec[kVectorLength];
|
||||||
|
|
||||||
for(int i = 0; i < kVectorLength; ++i) {
|
for (int i = 0; i < kVectorLength; ++i) {
|
||||||
Foo foo(0xABADCAFEABADCAFE + i, 10000 + i, '@' + i, 1000000 + i);
|
Foo foo(0xABADCAFEABADCAFE + i, 10000 + i, '@' + i, 1000000 + i);
|
||||||
Bar bar(foo, 123456 + i, 3.14159f + i, 10000 + i);
|
Bar bar(foo, 123456 + i, 3.14159f + i, 10000 + i);
|
||||||
auto name = fbb.CreateString("Hello, World!");
|
auto name = fbb.CreateString("Hello, World!");
|
||||||
auto foobar = CreateFooBar(fbb, &bar, name, 3.1415432432445543543 + i,
|
auto foobar =
|
||||||
'!' + i);
|
CreateFooBar(fbb, &bar, name, 3.1415432432445543543 + i, '!' + i);
|
||||||
vec[i] = foobar;
|
vec[i] = foobar;
|
||||||
}
|
}
|
||||||
auto location = fbb.CreateString("http://google.com/flatbuffers/");
|
auto location = fbb.CreateString("http://google.com/flatbuffers/");
|
||||||
auto foobarvec = fbb.CreateVector(vec, kVectorLength);
|
auto foobarvec = fbb.CreateVector(vec, kVectorLength);
|
||||||
auto foobarcontainer = CreateFooBarContainer(fbb, foobarvec, true,
|
auto foobarcontainer =
|
||||||
Enum_Bananas, location);
|
CreateFooBarContainer(fbb, foobarvec, true, Enum_Bananas, location);
|
||||||
fbb.Finish(foobarcontainer);
|
fbb.Finish(foobarcontainer);
|
||||||
|
|
||||||
len = fbb.GetSize();
|
len = fbb.GetSize();
|
||||||
return fbb.GetBufferPointer();
|
return fbb.GetBufferPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t Use(void *decoded) override {
|
int64_t Use(void *decoded) {
|
||||||
sum = 0;
|
sum = 0;
|
||||||
auto foobarcontainer = GetFooBarContainer(decoded);
|
auto foobarcontainer = GetFooBarContainer(decoded);
|
||||||
sum = 0;
|
sum = 0;
|
||||||
@@ -66,7 +65,7 @@ struct FlatBufferBench : Bench {
|
|||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *Decode(void *buffer, int64_t) override { return buffer; }
|
void *Decode(void *buffer, int64_t) { return buffer; }
|
||||||
void Dealloc(void *) override{};
|
void Dealloc(void *) override{};
|
||||||
|
|
||||||
FlatBufferBuilder fbb;
|
FlatBufferBuilder fbb;
|
||||||
|
|||||||
109
benchmarks/cpp/raw/raw_bench.cpp
Normal file
109
benchmarks/cpp/raw/raw_bench.cpp
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
#include "benchmarks/cpp/raw/raw_bench.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "benchmarks/cpp/bench.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const int64_t kStringLength = 32;
|
||||||
|
const int64_t kVectorLength = 3;
|
||||||
|
|
||||||
|
enum Enum { Apples, Pears, Bananas };
|
||||||
|
|
||||||
|
struct Foo {
|
||||||
|
int64_t id;
|
||||||
|
short count;
|
||||||
|
char prefix;
|
||||||
|
int length;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Bar {
|
||||||
|
Foo parent;
|
||||||
|
int time;
|
||||||
|
float ratio;
|
||||||
|
unsigned short size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FooBar {
|
||||||
|
Bar sibling;
|
||||||
|
// We have to stick this in, otherwise strlen() will make it slower than
|
||||||
|
// FlatBuffers:
|
||||||
|
int name_len;
|
||||||
|
char name[kStringLength];
|
||||||
|
double rating;
|
||||||
|
unsigned char postfix;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FooBarContainer {
|
||||||
|
FooBar list[kVectorLength]; // 3 copies of the above
|
||||||
|
bool initialized;
|
||||||
|
Enum fruit;
|
||||||
|
int location_len;
|
||||||
|
char location[kStringLength];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RawBench : Bench {
|
||||||
|
uint8_t *Encode(void *buf, int64_t &len) {
|
||||||
|
FooBarContainer *fbc = new (buf) FooBarContainer;
|
||||||
|
strcpy(fbc->location, "http://google.com/flatbuffers/"); // Unsafe eek!
|
||||||
|
fbc->location_len = (int)strlen(fbc->location);
|
||||||
|
fbc->fruit = Bananas;
|
||||||
|
fbc->initialized = true;
|
||||||
|
for (int i = 0; i < kVectorLength; i++) {
|
||||||
|
// We add + i to not make these identical copies for a more realistic
|
||||||
|
// compression test.
|
||||||
|
auto &foobar = fbc->list[i];
|
||||||
|
foobar.rating = 3.1415432432445543543 + i;
|
||||||
|
foobar.postfix = '!' + i;
|
||||||
|
strcpy(foobar.name, "Hello, World!");
|
||||||
|
foobar.name_len = (int)strlen(foobar.name);
|
||||||
|
auto &bar = foobar.sibling;
|
||||||
|
bar.ratio = 3.14159f + i;
|
||||||
|
bar.size = 10000 + i;
|
||||||
|
bar.time = 123456 + i;
|
||||||
|
auto &foo = bar.parent;
|
||||||
|
foo.id = 0xABADCAFEABADCAFE + i;
|
||||||
|
foo.count = 10000 + i;
|
||||||
|
foo.length = 1000000 + i;
|
||||||
|
foo.prefix = '@' + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = sizeof(FooBarContainer);
|
||||||
|
return reinterpret_cast<uint8_t *>(fbc);
|
||||||
|
};
|
||||||
|
|
||||||
|
int64_t Use(void *decoded) {
|
||||||
|
auto foobarcontainer = reinterpret_cast<FooBarContainer *>(decoded);
|
||||||
|
sum = 0;
|
||||||
|
Add(foobarcontainer->initialized);
|
||||||
|
Add(foobarcontainer->location_len);
|
||||||
|
Add(foobarcontainer->fruit);
|
||||||
|
for (unsigned int i = 0; i < kVectorLength; i++) {
|
||||||
|
auto foobar = &foobarcontainer->list[i];
|
||||||
|
Add(foobar->name_len);
|
||||||
|
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 *buf, int64_t) { return buf; }
|
||||||
|
void Dealloc(void *) override{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
std::unique_ptr<Bench> NewRawBench() {
|
||||||
|
return std::unique_ptr<RawBench>(new RawBench());
|
||||||
|
}
|
||||||
10
benchmarks/cpp/raw/raw_bench.h
Normal file
10
benchmarks/cpp/raw/raw_bench.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef BENCHMARKS_CPP_RAW_RAW_BENCH_H_
|
||||||
|
#define BENCHMARKS_CPP_RAW_RAW_BENCH_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "benchmarks/cpp/bench.h"
|
||||||
|
|
||||||
|
std::unique_ptr<Bench> NewRawBench();
|
||||||
|
|
||||||
|
#endif // BENCHMARKS_CPP_RAW_RAW_BENCH_H_
|
||||||
Reference in New Issue
Block a user