// Parse-time micro-benchmark — Phase A v1.10 yyjson swap. // // Compares nlohmann::json::parse against smartbotic::db::parse_to_nlohmann // on a corpus of JSON documents loaded from a file (one document per line). // Not a regression gate — informational, run by hand to capture the // parse-speed delta of the Phase A swap. #include #include #include #include #include #include #include #include "json_parse.hpp" int main(int argc, char** argv) { if (argc < 2) { std::cerr << "usage: bench_json_parse \n" << " corpus = one JSON document per line\n"; return 1; } std::ifstream f(argv[1]); if (!f) { std::cerr << "cannot open " << argv[1] << "\n"; return 1; } std::vector docs; std::string line; while (std::getline(f, line)) { if (!line.empty()) docs.push_back(line); } if (docs.empty()) { std::cerr << "empty corpus\n"; return 1; } std::cerr << "corpus: " << docs.size() << " documents\n"; constexpr int kIters = 5; auto bench = [&](const char* name, auto fn) { double best = 1e18; for (int i = 0; i < kIters; ++i) { auto t0 = std::chrono::steady_clock::now(); size_t sink = 0; for (const auto& s : docs) { auto j = fn(s); sink += j.size(); } auto t1 = std::chrono::steady_clock::now(); double ms = std::chrono::duration(t1 - t0).count(); best = std::min(best, ms); std::cerr << " " << name << " iter " << i << ": " << ms << " ms (sink=" << sink << ")\n"; } return best; }; double nl = bench("nlohmann", [](const std::string& s) { return nlohmann::json::parse(s); }); double yy = bench("yyjson ", [](const std::string& s) { return smartbotic::db::parse_to_nlohmann(s); }); std::cout << "best nlohmann: " << nl << " ms\n"; std::cout << "best yyjson: " << yy << " ms\n"; std::cout << "speedup: " << (nl / yy) << "x\n"; return 0; }