mirror of
https://github.com/morluto/rea
synced 2026-10-27 22:45:19 -04:00
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:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user