Skip to content

Commit

Permalink
Optimize output vector adapter write (#3569)
Browse files Browse the repository at this point in the history
* Add benchmark for cbor serialization and cbor binary data serialization

* Use std::vector::insert method instead of std::copy in output_vector_adapter::write_characters

This change increases a lot the performance when writing lots of binary data.
  • Loading branch information
romainreignier authored Jul 8, 2022
1 parent 7d361ec commit d4daaa8
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 2 deletions.
2 changes: 1 addition & 1 deletion include/nlohmann/detail/output/output_adapters.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class output_vector_adapter : public output_adapter_protocol<CharType>
JSON_HEDLEY_NON_NULL(2)
void write_characters(const CharType* s, std::size_t length) override
{
std::copy(s, s + length, std::back_inserter(v));
v.insert(v.end(), s, s + length);
}

private:
Expand Down
2 changes: 1 addition & 1 deletion single_include/nlohmann/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14250,7 +14250,7 @@ class output_vector_adapter : public output_adapter_protocol<CharType>
JSON_HEDLEY_NON_NULL(2)
void write_characters(const CharType* s, std::size_t length) override
{
std::copy(s, s + length, std::back_inserter(v));
v.insert(v.end(), s, s + length);
}

private:
Expand Down
61 changes: 61 additions & 0 deletions tests/benchmarks/src/benchmarks.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "benchmark/benchmark.h"
#include <nlohmann/json.hpp>
#include <fstream>
#include <numeric>
#include <vector>
#include <test_data.hpp>

using json = nlohmann::json;
Expand Down Expand Up @@ -107,4 +109,63 @@ BENCHMARK_CAPTURE(Dump, small_signed_ints / -, TEST_DATA_DIRECTORY "/regression/
BENCHMARK_CAPTURE(Dump, small_signed_ints / 4, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json", 4);


//////////////////////////////////////////////////////////////////////////////
// serialize CBOR
//////////////////////////////////////////////////////////////////////////////
static void ToCbor(benchmark::State& state, const char* filename)
{
std::ifstream f(filename);
std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
json j = json::parse(str);

while (state.KeepRunning())
{
json::to_cbor(j);
}

state.SetBytesProcessed(state.iterations() * json::to_cbor(j).size());
}
BENCHMARK_CAPTURE(ToCbor, jeopardy, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json");
BENCHMARK_CAPTURE(ToCbor, canada, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json");
BENCHMARK_CAPTURE(ToCbor, citm_catalog, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json");
BENCHMARK_CAPTURE(ToCbor, twitter, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json");
BENCHMARK_CAPTURE(ToCbor, floats, TEST_DATA_DIRECTORY "/regression/floats.json");
BENCHMARK_CAPTURE(ToCbor, signed_ints, TEST_DATA_DIRECTORY "/regression/signed_ints.json");
BENCHMARK_CAPTURE(ToCbor, unsigned_ints, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json");
BENCHMARK_CAPTURE(ToCbor, small_signed_ints, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json");

//////////////////////////////////////////////////////////////////////////////
// serialize binary CBOR
//////////////////////////////////////////////////////////////////////////////
static void BinaryToCbor(benchmark::State& state)
{
std::vector<uint8_t> data(256);
std::iota(data.begin(), data.end(), 0);

auto it = data.begin();
std::vector<uint8_t> in;
in.reserve(state.range(0));
for (int i = 0; i < state.range(0); ++i)
{
if (it == data.end())
{
it = data.begin();
}

in.push_back(*it);
++it;
}

json::binary_t bin{in};
json j{{"type", "binary"}, {"data", bin}};

while (state.KeepRunning())
{
json::to_cbor(j);
}

state.SetBytesProcessed(state.iterations() * json::to_cbor(j).size());
}
BENCHMARK(BinaryToCbor)->RangeMultiplier(2)->Range(8, 8 << 12);

BENCHMARK_MAIN();

0 comments on commit d4daaa8

Please sign in to comment.