#include #include #include #include #include #include #include #include #include #include #include using namespace yams; using namespace yams::metadata; namespace { struct RepoContext { std::filesystem::path dbPath; std::unique_ptr pool; std::unique_ptr repo; }; DocumentInfo makeDocWithPath(const std::string& path, const std::string& hash) { DocumentInfo info; info.filePath = path; info.fileName = std::filesystem::path(path).filename().string(); info.fileExtension = std::filesystem::path(path).extension().string(); info.fileSize = 1764; info.sha256Hash = hash; info.mimeType = info.fileExtension == ".pdf" ? "application/pdf" : "text/plain"; auto now_s = std::chrono::floor(std::chrono::system_clock::now()); info.createdTime = now_s; info.modifiedTime = now_s; info.indexedTime = now_s; info.contentExtracted = true; info.extractionStatus = ExtractionStatus::Success; auto derived = computePathDerivedValues(path); info.filePath = derived.normalizedPath; info.pathPrefix = derived.pathPrefix; info.reversePath = derived.reversePath; info.pathHash = derived.pathHash; info.parentHash = derived.parentHash; info.pathDepth = derived.pathDepth; return info; } RepoContext makeRepositoryWithDocs(std::size_t count) { RepoContext ctx; ctx.dbPath = std::filesystem::temp_directory_path() / ("metadata_query_bench_" + std::to_string(std::rand()) + ".db"); std::filesystem::remove(ctx.dbPath); ConnectionPoolConfig config; config.minConnections = 1; config.maxConnections = 2; ctx.pool = std::make_unique(ctx.dbPath.string(), config); auto init = ctx.pool->initialize(); if (!init) throw std::runtime_error("Failed to initialize pool: " + init.error().message); ctx.repo = std::make_unique(*ctx.pool); for (std::size_t i = 0; i < count; ++i) { auto dir = "/workspace/project" + std::to_string(i % 16); auto basename = std::string("file_") + std::to_string(i) + ((i % 5 == 0) ? ".md" : ".txt"); auto path = dir + "/" + basename; auto hash = "HASH" + std::to_string(i) + std::string(60, 'A' + (i % 16)); auto doc = makeDocWithPath(path, hash.substr(0, 64)); auto inserted = ctx.repo->insertDocument(doc); if (!inserted) throw std::runtime_error("insertDocument failed: " + inserted.error().message); } return ctx; } class MetadataQueryFixture : public benchmark::Fixture { public: void SetUp(const ::benchmark::State& state) override { std::size_t count = static_cast(state.range(0)); ctx_ = makeRepositoryWithDocs(count); } void TearDown(const ::benchmark::State&) override { ctx_.repo.reset(); if (ctx_.pool) ctx_.pool->shutdown(); ctx_.pool.reset(); std::error_code ec; std::filesystem::remove(ctx_.dbPath, ec); } protected: RepoContext ctx_; }; BENCHMARK_DEFINE_F(MetadataQueryFixture, QueryExactPath)(benchmark::State& state) { DocumentQueryOptions opts; // i=5 is always present for Arg(128)/Arg(1024) and routes to project5 (i % 16). opts.exactPath = "/workspace/project5/file_5.md"; for (auto _ : state) { auto res = ctx_.repo->queryDocuments(opts); benchmark::DoNotOptimize(res); if (!res) state.SkipWithError("queryDocuments exact path failed"); else if (res.value().empty()) state.SkipWithError("queryDocuments exact path returned no results"); } } BENCHMARK_DEFINE_F(MetadataQueryFixture, QueryDirectoryPrefix)(benchmark::State& state) { DocumentQueryOptions opts; opts.pathPrefix = "/workspace/project7"; opts.prefixIsDirectory = true; opts.includeSubdirectories = true; for (auto _ : state) { auto res = ctx_.repo->queryDocuments(opts); benchmark::DoNotOptimize(res); if (!res) state.SkipWithError("queryDocuments prefix failed"); } } BENCHMARK_DEFINE_F(MetadataQueryFixture, QuerySuffixFts)(benchmark::State& state) { DocumentQueryOptions opts; opts.containsFragment = "file_11.md"; opts.containsUsesFts = true; for (auto _ : state) { auto res = ctx_.repo->queryDocuments(opts); benchmark::DoNotOptimize(res); if (!res) state.SkipWithError("queryDocuments suffix failed"); } } BENCHMARK_REGISTER_F(MetadataQueryFixture, QueryExactPath)->Arg(128)->Arg(1024); BENCHMARK_REGISTER_F(MetadataQueryFixture, QueryDirectoryPrefix)->Arg(128)->Arg(1024); BENCHMARK_REGISTER_F(MetadataQueryFixture, QuerySuffixFts)->Arg(128)->Arg(1024); } // namespace BENCHMARK_MAIN();