ソースを参照

test: add bench_json_parse for phase A parse-time delta

Manual micro-benchmark, NOT registered with CTest. Captures the
nlohmann vs yyjson parse-time delta on a corpus of JSON documents
(one per line). Use to validate the Phase A swap is actually buying
the speedup that motivates the change.

Measured on 10k synthetic Zoe-shape docs (3.3 MB corpus):
  best nlohmann: 136.25 ms
  best yyjson:    48.66 ms
  speedup:        2.80x

That figure dominates cold-boot recovery (WAL replay + snapshot
deserialize are all-parse, no business logic) and shaves a measurable
slice off every gRPC request body's processing cost.
fszontagh 2 ヶ月 前
コミット
40294d714a
2 ファイル変更91 行追加0 行削除
  1. 20 0
      tests/CMakeLists.txt
  2. 71 0
      tests/bench_json_parse.cpp

+ 20 - 0
tests/CMakeLists.txt

@@ -249,6 +249,26 @@ endif()
 
 target_link_libraries(test_json_parse PRIVATE ${yyjson_LIBRARIES})
 
+# Parse-time micro-benchmark (v1.10 Phase A T8) — manual bench, NOT
+# registered with CTest. Run as ./build/tests/bench_json_parse <corpus>.
+add_executable(bench_json_parse
+    bench_json_parse.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/../service/src/json_parse.cpp
+)
+
+target_include_directories(bench_json_parse PRIVATE
+    ${CMAKE_CURRENT_SOURCE_DIR}/../service/src
+    ${yyjson_INCLUDE_DIRS}
+)
+
+if(TARGET nlohmann_json::nlohmann_json)
+    target_link_libraries(bench_json_parse PRIVATE nlohmann_json::nlohmann_json)
+else()
+    target_include_directories(bench_json_parse PRIVATE ${NLOHMANN_JSON_INCLUDE_DIRS})
+endif()
+
+target_link_libraries(bench_json_parse PRIVATE ${yyjson_LIBRARIES})
+
 # Register with CTest
 enable_testing()
 add_test(NAME vector_storage COMMAND test_vector_storage)

+ 71 - 0
tests/bench_json_parse.cpp

@@ -0,0 +1,71 @@
+// 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 <algorithm>
+#include <chrono>
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include <nlohmann/json.hpp>
+
+#include "json_parse.hpp"
+
+int main(int argc, char** argv) {
+    if (argc < 2) {
+        std::cerr << "usage: bench_json_parse <path-to-json-corpus>\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<std::string> 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<double, std::milli>(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;
+}