Lumi/scripts/benchmark-okf-search.js
2026-07-17 22:10:00 +02:00

83 lines
3.1 KiB
JavaScript

"use strict";
const assert = require("assert");
const fs = require("fs");
const os = require("os");
const path = require("path");
const { performance } = require("perf_hooks");
const { ensureKnowledgeDirs, searchFileKnowledge } = require("../plugins/okf/backend/file_knowledge");
const fixtureCount = Math.max(100, Math.min(Number(process.argv[2]) || 1000, 10000));
const queryCount = 120;
const root = fs.mkdtempSync(path.join(os.tmpdir(), "lumi-okf-benchmark-"));
const user = { id: "benchmark-user" };
const admin = { id: "benchmark-admin", isAdmin: true, isMod: true };
try {
ensureKnowledgeDirs(root);
const community = path.join(root, "knowledge", "community");
for (let index = 0; index < fixtureCount; index += 1) {
const visibility = index % 20 === 0 ? "admin" : "user";
const secret = visibility === "admin" ? "sealedterm " : "";
fs.writeFileSync(path.join(community, `fixture-${index}.md`), [
"---",
`id: benchmark.fixture-${index}`,
`title: Benchmark topic ${index}`,
"scope: community",
"status: active",
`visibility: ${visibility}`,
`priority: ${index % 7}`,
`tags: benchmark, topic-${index % 50}`,
"---",
`# Topic ${index}`,
`${secret}Support guidance for fixture ${index}, group ${index % 50}, and setting ${index % 17}.`,
"This paragraph adds enough ordinary text to approximate a small knowledge entry."
].join("\n"));
}
const coldStart = performance.now();
const coldResults = searchFileKnowledge({ query: "topic 42 setting", user, rootDir: root, limit: 5 });
const coldMs = performance.now() - coldStart;
assert(coldResults.length > 0);
const timings = [];
for (let index = 0; index < queryCount; index += 1) {
const started = performance.now();
const results = searchFileKnowledge({
query: `topic ${index % 50} setting ${index % 17}`,
user,
rootDir: root,
limit: 5
});
timings.push(performance.now() - started);
assert(results.length > 0);
}
assert.equal(searchFileKnowledge({ query: "sealedterm", user, rootDir: root, limit: 25 }).length, 0);
assert(searchFileKnowledge({ query: "sealedterm", user: admin, rootDir: root, limit: 25 }).length > 0);
const changedPath = path.join(community, "fixture-1.md");
fs.appendFileSync(changedPath, "\nuniquelychangedterm\n");
assert(searchFileKnowledge({ query: "uniquelychangedterm", user, rootDir: root, limit: 5 }).length > 0);
fs.rmSync(changedPath);
assert.equal(searchFileKnowledge({ query: "uniquelychangedterm", user, rootDir: root, limit: 5 }).length, 0);
timings.sort((a, b) => a - b);
const percentile = (fraction) => timings[Math.min(timings.length - 1, Math.floor(timings.length * fraction))];
const result = {
fixtures: fixtureCount,
queries: queryCount,
cold_ms: round(coldMs),
warm_median_ms: round(percentile(0.5)),
warm_p95_ms: round(percentile(0.95)),
warm_max_ms: round(timings[timings.length - 1])
};
console.log(JSON.stringify(result, null, 2));
} finally {
fs.rmSync(root, { recursive: true, force: true });
}
function round(value) {
return Math.round(value * 100) / 100;
}