Created
October 13, 2019 11:01
-
-
Save willir/4c97942b26b51ae9c72d21f80e54805a to your computer and use it in GitHub Desktop.
Benchmark of rapidjson BasicOstreamWrapper vs BufferedOStreamWrapper.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// To Compile: g++ -O3 -std=c++17 -I${RAPIDJSON_INCLUDE} rapidjson-ostream-wrapper-benchmark.cpp -lbenchmark | |
#include <sstream> | |
#include <cstdlib> | |
#include <memory> | |
#include <random> | |
#include <string> | |
#include <string_view> | |
#define RAPIDJSON_HAS_STDSTRING 1 | |
#include <rapidjson/bufferedostreamwrapper.h> | |
#include <rapidjson/ostreamwrapper.h> | |
#include <rapidjson/stringbuffer.h> | |
#include <rapidjson/writer.h> | |
#include <benchmark/benchmark.h> | |
class Random { | |
public: | |
Random() : gen_(std::make_unique<std::mt19937>(std::random_device{}())) {} | |
std::string GenStr(size_t len) { | |
std::string res(len, '\0'); | |
for (size_t i = 0; i < len; ++i) { | |
const auto id = | |
std::uniform_int_distribution<size_t>{0, ALPHABET.size() - 1}(*gen_); | |
res[i] = ALPHABET[id]; | |
} | |
return res; | |
} | |
int64_t GenRandomDouble() { | |
return std::uniform_real_distribution<double>{-10000, 10000}(*gen_); | |
} | |
int64_t GenInt64() { return std::uniform_int_distribution<int64_t>{}(*gen_); } | |
uint64_t GenUint64() { | |
return std::uniform_int_distribution<uint64_t>{}(*gen_); | |
} | |
private: | |
static constexpr std::string_view ALPHABET = | |
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'\""; | |
std::unique_ptr<std::mt19937> gen_; | |
}; | |
struct Foo { | |
std::string str; | |
int64_t num1; | |
uint64_t num2; | |
double real_num; | |
explicit Foo(Random &gen) | |
: str(gen.GenStr(15)), num1(gen.GenInt64()), num2(gen.GenUint64()), | |
real_num(gen.GenRandomDouble()) {} | |
}; | |
static constexpr size_t INPUT_LEN = 10000; | |
static std::vector<Foo> GenerateInput() { | |
std::vector<Foo> res; | |
res.reserve(INPUT_LEN); | |
Random gen; | |
for (size_t i = 0; i < INPUT_LEN; ++i) { | |
res.emplace_back(gen); | |
} | |
return res; | |
} | |
static std::vector<Foo> GetInput() { | |
static const std::vector<Foo> input_arr = GenerateInput(); | |
return input_arr; | |
} | |
template <typename Writer> | |
static void Write(const std::vector<Foo> &foo_list, Writer &writer) { | |
writer.StartArray(); | |
for (const auto &foo : foo_list) { | |
writer.StartObject(); | |
writer.Key("my_string"); | |
writer.String(foo.str); | |
writer.Key("my_number1"); | |
writer.Int64(foo.num1); | |
writer.Key("my_number2"); | |
writer.Uint64(foo.num2); | |
writer.Key("my_real_number"); | |
writer.Double(foo.real_num); | |
writer.EndObject(); | |
} | |
writer.EndArray(); | |
} | |
static std::string ToStringStringBuffer(const std::vector<Foo> &foo_list) { | |
rapidjson::StringBuffer ss; | |
{ | |
rapidjson::Writer<rapidjson::StringBuffer> writer(ss); | |
Write(foo_list, writer); | |
} | |
return ss.GetString(); | |
} | |
static std::string ToStringOStreamWrapper(const std::vector<Foo> &foo_list) { | |
std::stringstream ss; | |
{ | |
rapidjson::OStreamWrapper wrapper(ss); | |
rapidjson::Writer<rapidjson::OStreamWrapper> writer(wrapper); | |
Write(foo_list, writer); | |
} | |
return ss.str(); | |
} | |
static std::string | |
ToStringBufferedOStreamWrapper(const std::vector<Foo> &foo_list) { | |
std::stringstream ss; | |
{ | |
rapidjson::BufferedOStreamWrapper<> wrapper(ss); | |
rapidjson::Writer<rapidjson::BufferedOStreamWrapper<>> writer(wrapper); | |
Write(foo_list, writer); | |
} | |
return ss.str(); | |
} | |
static void BenchmarkStringBuffer(benchmark::State &state) { | |
const auto foo_list = GetInput(); | |
for (auto _ : state) { | |
auto res = ToStringStringBuffer(foo_list); | |
benchmark::DoNotOptimize(res); | |
} | |
} | |
static void BenchmarkBufferedOStreamWrapper(benchmark::State &state) { | |
const auto foo_list = GetInput(); | |
for (auto _ : state) { | |
auto res = ToStringBufferedOStreamWrapper(foo_list); | |
benchmark::DoNotOptimize(res); | |
} | |
} | |
static void BenchmarkOStreamWrapper(benchmark::State &state) { | |
const auto foo_list = GetInput(); | |
for (auto _ : state) { | |
auto res = ToStringOStreamWrapper(foo_list); | |
benchmark::DoNotOptimize(res); | |
} | |
} | |
BENCHMARK(BenchmarkStringBuffer); | |
BENCHMARK(BenchmarkBufferedOStreamWrapper); | |
BENCHMARK(BenchmarkOStreamWrapper); | |
BENCHMARK_MAIN(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment