/// bench_spatial.cpp — R-Tree / KD-Tree build + kNN benchmarks /// /// Metrics: /// RTree_Build/N{size} — STR-bulk-build time for N random 3D points /// RTree_kNN/N{size} — kNN(n=10) queries on a pre-built R-Tree /// KDTree_Build/N{size} — build time for N random 3D points /// KDTree_kNN/N{size} — kNN(n=10) queries on a pre-built KD-Tree #include #include #include #include #include #include using namespace vde; namespace { std::vector random_points_3d(int n, double R = 100.0) { std::mt19937 rng(42); std::uniform_real_distribution dist(-R, R); std::vector pts; pts.reserve(n); for (int i = 0; i < n; ++i) pts.emplace_back(dist(rng), dist(rng), dist(rng)); return pts; } /// 20 random query points for kNN std::vector query_points(int n = 20, double R = 100.0) { return random_points_3d(n, R); } } // namespace // ── R-Tree ──────────────────────────────────────────────────────────── static void RTree_Build(benchmark::State& state) { auto pts = random_points_3d(state.range(0)); for (auto _ : state) { spatial::RTree tree; tree.build(pts); benchmark::DoNotOptimize(tree.size()); } state.SetItemsProcessed(state.iterations() * state.range(0)); } BENCHMARK(RTree_Build)->Arg(500)->Arg(1000)->Arg(2000); class RTreeFixture : public benchmark::Fixture { public: void SetUp(const benchmark::State& state) override { points = random_points_3d(state.range(0)); tree.build(points); queries = query_points(); } spatial::RTree tree; std::vector points; std::vector queries; }; BENCHMARK_DEFINE_F(RTreeFixture, RTree_kNN)(benchmark::State& state) { size_t total = 0; for (auto _ : state) { for (const auto& q : queries) { auto result = tree.query_knn(q, 10); total += result.size(); } } benchmark::DoNotOptimize(total); state.SetItemsProcessed(state.iterations() * queries.size()); } BENCHMARK_REGISTER_F(RTreeFixture, RTree_kNN)->Arg(500)->Arg(1000)->Arg(2000); // ── KD-Tree ────────────────────────────────────────────────────────── static void KDTree_Build(benchmark::State& state) { auto pts = random_points_3d(state.range(0)); for (auto _ : state) { spatial::KDTree tree; tree.build(pts); benchmark::DoNotOptimize(tree.size()); } state.SetItemsProcessed(state.iterations() * state.range(0)); } BENCHMARK(KDTree_Build)->Arg(500)->Arg(1000)->Arg(2000); class KDTreeFixture : public benchmark::Fixture { public: void SetUp(const benchmark::State& state) override { points = random_points_3d(state.range(0)); tree.build(points); queries = query_points(); } spatial::KDTree tree; std::vector points; std::vector queries; }; BENCHMARK_DEFINE_F(KDTreeFixture, KDTree_kNN)(benchmark::State& state) { size_t total = 0; for (auto _ : state) { for (const auto& q : queries) { auto result = tree.query_knn(q, 10); total += result.size(); } } benchmark::DoNotOptimize(total); state.SetItemsProcessed(state.iterations() * queries.size()); } BENCHMARK_REGISTER_F(KDTreeFixture, KDTree_kNN)->Arg(500)->Arg(1000)->Arg(2000);