mirror of
https://github.com/nlohmann/json.git
synced 2026-11-04 11:49:22 +00:00
docs: add the blog post "How 3.13.0 got faster"
A post for the documentation (Home > Blog) on how 3.13.0 became faster: eight themes with the pull requests behind them, the ideas taken from other libraries, what did not work, how the fast paths are tested, and the compile-time cost. Every number comes from a run on 2026-10-27 (3.12.0 against develop plus the open non-draft PRs, Apple M1 Max) or from the linked PR. - docs/mkdocs/docs/home/blog/how_3_13_0_got_faster.md: the post. - docs/mkdocs/scripts/figures/perf_blog.py: draws its 12 figures (overview, eight timeline panels, the SWAR test, the cliffs, json_view throughput) as inline SVGs in the nj-charts style; data/perf_timeline.csv holds the timeline. - tests/benchmarks/history: history.cpp and history.py time one fixed program against the header of every commit that changed it, interleaved, and write one CSV row per commit with its PR. The timeline of the post comes from it. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
21 files changed
+2297
No files matched your search
@@ -0,0 +1,88 @@
|
||||
// __ _____ _____ _____
|
||||
// __| | __| | | | JSON for Modern C++ (supporting code)
|
||||
// | | |__ | | | | | | version 3.12.0
|
||||
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// One fixed benchmark, compiled against the json.hpp of every commit that changed it (see README.md).
|
||||
// It uses only API that 3.12.0 has; the json_document rows exist only where the header has json_view.hpp.
|
||||
// Usage: history <dir with twitter.json, citm_catalog.json, canada.json and citm_compact.json>
|
||||
// Prints one line per workload: the name and the median of 9 batches in microseconds per call.
|
||||
#include <nlohmann/json.hpp>
|
||||
#if __has_include(<nlohmann/json_view.hpp>) && !defined(HISTORY_NO_VIEW)
|
||||
#include <nlohmann/json_view.hpp>
|
||||
#define HISTORY_VIEW 1
|
||||
#endif
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using nlohmann::json;
|
||||
static std::string slurp(const std::string& p)
|
||||
{
|
||||
std::ifstream f(p, std::ios::binary);
|
||||
std::stringstream s;
|
||||
s << f.rdbuf();
|
||||
return s.str();
|
||||
}
|
||||
static volatile std::size_t sink;
|
||||
|
||||
static void bench(const char* name, const std::function<std::size_t()>& f)
|
||||
{
|
||||
using clk = std::chrono::steady_clock;
|
||||
sink = f(); // warm up
|
||||
std::size_t n = 1;
|
||||
for (;;)
|
||||
{
|
||||
auto t0 = clk::now();
|
||||
for (std::size_t i = 0; i < n; ++i) sink = f();
|
||||
double dt = std::chrono::duration<double>(clk::now() - t0).count();
|
||||
if (dt > 0.02) break;
|
||||
n *= 2;
|
||||
}
|
||||
std::vector<double> v;
|
||||
for (int b = 0; b < 9; ++b)
|
||||
{
|
||||
auto t0 = clk::now();
|
||||
for (std::size_t i = 0; i < n; ++i) sink = f();
|
||||
v.push_back(std::chrono::duration<double, std::micro>(clk::now() - t0).count() / n);
|
||||
}
|
||||
std::sort(v.begin(), v.end());
|
||||
std::printf("%s %.3f\n", name, v[4]);
|
||||
}
|
||||
|
||||
int main(int, char** argv)
|
||||
{
|
||||
std::string d = argv[1];
|
||||
const std::string tw = slurp(d + "/twitter.json"), ci = slurp(d + "/citm_catalog.json"),
|
||||
ca = slurp(d + "/canada.json"), cii = slurp(d + "/citm_compact.json");
|
||||
const json jtw = json::parse(tw), jci = json::parse(ci), jca = json::parse(ca);
|
||||
const std::vector<std::uint8_t> cbtw = json::to_cbor(jtw);
|
||||
|
||||
bench("parse_twitter", [&] { return json::parse(tw).size(); });
|
||||
bench("parse_citm", [&] { return json::parse(ci).size(); });
|
||||
bench("parse_canada", [&] { return json::parse(ca).size(); });
|
||||
bench("parse_citm_compact", [&] { return json::parse(cii).size(); });
|
||||
bench("parse_twitter_ifstream", [&] { std::ifstream f(d + "/twitter.json"); return json::parse(f).size(); });
|
||||
bench("accept_twitter", [&] { return static_cast<std::size_t>(json::accept(tw)); });
|
||||
#ifdef HISTORY_VIEW
|
||||
bench("view_parse_twitter", [&] { const auto doc = nlohmann::json_document::parse(tw); return doc.root().size(); });
|
||||
bench("view_parse_citm", [&] { const auto doc = nlohmann::json_document::parse(ci); return doc.root().size(); });
|
||||
bench("view_parse_canada", [&] { const auto doc = nlohmann::json_document::parse(ca); return doc.root().size(); });
|
||||
#endif
|
||||
bench("dump_twitter", [&] { return jtw.dump().size(); });
|
||||
bench("dump_citm", [&] { return jci.dump().size(); });
|
||||
bench("dump_canada", [&] { return jca.dump().size(); });
|
||||
bench("dump4_citm", [&] { return jci.dump(4).size(); });
|
||||
bench("from_cbor_twitter", [&] { return json::from_cbor(cbtw).size(); });
|
||||
bench("to_cbor_twitter", [&] { return json::to_cbor(jtw).size(); });
|
||||
bench("copy_destroy_citm", [&] { json c = jci; return c.size(); });
|
||||
bench("equal_citm", [&] { json c = jci; return static_cast<std::size_t>(c == jci); });
|
||||
}
|
||||
Reference in new issue
Block a user