mirror of
https://github.com/NeuralNomadsAI/CodeNomad.git
synced 2026-10-21 05:06:37 +00:00
## Summary - Continue sparse history scans until a bounded result page is filled, publishing matches progressively across sessions. - Remove the automatic count traversal. Show page-local results and messages scanned directly from search responses, with no scan when opening an empty search. - Project text-only content in SQLite, reduce bounded RPC round trips, and share identical location checks only inside a request. ## Validation - UI/server typechecks and targeted server/store tests passed. - Chromium regression covers progressive results, pagination, workspace scope, technical toggle, empty results and absence of statistics requests. - Isolated native OpenCode 2.0.22 fixture passed, including all 242 workspace matches across two sessions and pruning/ownership regressions. - Synthetic benchmark: text search materializes 9.6 KB instead of 145 MB; CPU gain is modest because SQLite still parses stored JSON. See dev-docs/SESSION_HISTORY_QUERIES.md. ## Review Independent gatekeeper review and post-rebase validation in progress; findings will be addressed before administrator merge.
74 lines
3.4 KiB
JavaScript
74 lines
3.4 KiB
JavaScript
// Synthetic in-memory database only. Compare this checkout with a Git revision:
|
|
// node scripts/benchmark-session-history.mjs [baseline-ref]
|
|
import assert from "node:assert/strict"
|
|
import { execFileSync } from "node:child_process"
|
|
import { DatabaseSync } from "node:sqlite"
|
|
import { readFileSync } from "node:fs"
|
|
import { dirname, resolve } from "node:path"
|
|
import { fileURLToPath } from "node:url"
|
|
import { build } from "esbuild"
|
|
|
|
const root = fileURLToPath(new URL("..", import.meta.url))
|
|
const source = "packages/server/src/opencode/session-pruning/history-store.ts"
|
|
const baseline = process.argv[2] ?? "HEAD"
|
|
const implementations = []
|
|
for (const [name, contents] of [
|
|
[baseline, execFileSync("git", ["show", `${baseline}:${source}`], { cwd: root, encoding: "utf8" })],
|
|
["working tree", readFileSync(resolve(root, source), "utf8")],
|
|
]) {
|
|
const result = await build({ stdin: { contents, resolveDir: dirname(resolve(root, source)), loader: "ts" },
|
|
bundle: true, write: false, format: "esm", platform: "node" })
|
|
const { queryHistoryPage } = await import(`data:text/javascript;base64,${Buffer.from(result.outputFiles[0].text).toString("base64")}`)
|
|
implementations.push([name, queryHistoryPage])
|
|
}
|
|
const db = new DatabaseSync(":memory:")
|
|
db.exec(`CREATE TABLE session_v2(id TEXT PRIMARY KEY, directory TEXT, workspace_id TEXT, project_id TEXT);
|
|
CREATE TABLE session_message(id TEXT PRIMARY KEY, session_id TEXT, type TEXT, data TEXT);
|
|
INSERT INTO session_v2 VALUES ('s', '/repo', NULL, 'p')`)
|
|
const insert = db.prepare("INSERT INTO session_message VALUES (?, 's', 'assistant', ?)")
|
|
const payload = JSON.stringify({ content: [
|
|
{ type: "reasoning", text: "thinking ".repeat(10000) },
|
|
{ type: "tool", state: { content: [{ type: "text", text: "large output ".repeat(80000) }] } },
|
|
{ type: "text", text: "A searchable needle answer" },
|
|
] })
|
|
for (let n = 0; n < 128; n++) insert.run(`m-${n}`, payload)
|
|
let materialized = 0
|
|
const prepare = db.prepare.bind(db)
|
|
db.prepare = sql => {
|
|
const statement = prepare(sql)
|
|
if (sql.includes("AS data")) {
|
|
const iterate = statement.iterate.bind(statement)
|
|
statement.iterate = function* (...params) {
|
|
for (const row of iterate(...params)) {
|
|
materialized += typeof row.data === "string" ? Buffer.byteLength(row.data) : 0
|
|
yield row
|
|
}
|
|
}
|
|
}
|
|
return statement
|
|
}
|
|
try {
|
|
for (const purpose of ["stats", "search"]) {
|
|
for (const [name, queryHistoryPage] of implementations) {
|
|
const times = []
|
|
for (let run = 0; run < 4; run++) {
|
|
const start = performance.now()
|
|
let cursor, scanned = 0, hits = 0
|
|
materialized = 0
|
|
do {
|
|
const page = await queryHistoryPage(db, { directory: "/repo", sessionID: "s", projectID: "p" },
|
|
{ purpose, query: purpose === "search" ? "needle" : "", includeTechnical: false, cursor }, new AbortController().signal)
|
|
cursor = page.cursor ?? undefined
|
|
scanned += page.scanned
|
|
hits += page.hits.length
|
|
assert.equal(page.skipped, 0)
|
|
} while (cursor)
|
|
assert.equal(scanned, 128)
|
|
assert.equal(hits, purpose === "search" ? 128 : 0)
|
|
if (run) times.push(performance.now() - start)
|
|
}
|
|
times.sort((a, b) => a - b)
|
|
console.log(JSON.stringify({ purpose, implementation: name, medianMs: Math.round(times[1]), materializedBytes: materialized }))
|
|
}
|
|
}
|
|
} finally { db.close() }
|