perf(javascript): hash each semantic evidence context once (#1457)

The semantic graph's evidence-context registry canonicalized the full
provenance context three times for every node, relation, unknown and
fingerprint: once to hash its ID and twice more to compare against the
stored row. A file has only a few distinct contexts, so nearly all of
that work repeated a known answer.

Interning now keys contexts by their canonical text. Each fact
canonicalizes once, and only a new context is hashed and checked for a
digest collision. IDs and output are unchanged; Obsidian's 334 MB
Evidence is byte-identical and analysis drops from about 47.0 s to
44.4 s.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kaoru0822
2026-10-09 23:21:07 -07:00
committed by GitHub
parent 2781cad201
commit ef96657d6b
2 changed files with 55 additions and 8 deletions
@@ -56,6 +56,9 @@ const evidenceContextId = (context: ApplicationGraphEvidenceContext): string =>
/** Graph-scoped owner for canonical provenance shared by semantic facts. */
export class JavaScriptSemanticEvidenceContextRegistry {
readonly #contexts = new Map<string, JavaScriptSemanticEvidenceContext>();
// Facts share a few contexts, so key them by canonical text and hash each
// distinct context once instead of on every fact.
readonly #idsByCanonicalContext = new Map<string, string>();
/** Intern normalized non-location provenance at fact construction. */
intern(
@@ -63,18 +66,21 @@ export class JavaScriptSemanticEvidenceContextRegistry {
): JavaScriptSemanticEvidenceReference {
const normalized = normalizeEvidence(evidence);
const { location, ...context } = normalized;
const canonicalContext = canonicalJson(
context,
"JavaScript semantic graph",
);
const internedId = this.#idsByCanonicalContext.get(canonicalContext);
if (internedId !== undefined) return { context_id: internedId, location };
const contextId = evidenceContextId(context);
const row = { ...context, context_id: contextId };
const existing = this.#contexts.get(contextId);
if (
existing !== undefined &&
canonicalJson(existing, "JavaScript semantic graph") !==
canonicalJson(row, "JavaScript semantic graph")
)
// This canonical context is new, so a row already stored under its
// digest holds different provenance.
if (this.#contexts.has(contextId))
throw new TypeError(
"JavaScript semantic evidence context digest collision",
);
this.#contexts.set(contextId, row);
this.#contexts.set(contextId, { ...context, context_id: contextId });
this.#idsByCanonicalContext.set(canonicalContext, contextId);
return { context_id: contextId, location };
}
@@ -101,6 +107,7 @@ export class JavaScriptSemanticEvidenceContextRegistry {
/** Release interned contexts after the owning graph is finalized. */
clear(): void {
this.#contexts.clear();
this.#idsByCanonicalContext.clear();
}
}