From b4b7ebc787d6044e49ee6b5d4b63b728088ce648 Mon Sep 17 00:00:00 2001 From: Edgar Arakelyan Date: Tue, 20 Oct 2026 09:24:54 -0700 Subject: [PATCH] perf(environment): intersect list identity candidates through a set The list planner filtered each recording's candidate fields with a linear includes per candidate, even on the first recording, so a one-item list with tens of thousands of suffix-named fields cost hundreds of millions of comparisons. The first recording's candidates now stand as they are and later recordings intersect through a set. Co-Authored-By: Claude Opus 5.5 --- src/domain/analysisView/EnvironmentStateExtraction.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/domain/analysisView/EnvironmentStateExtraction.ts b/src/domain/analysisView/EnvironmentStateExtraction.ts index 047febe554..e59cbf056f 100644 --- a/src/domain/analysisView/EnvironmentStateExtraction.ts +++ b/src/domain/analysisView/EnvironmentStateExtraction.ts @@ -347,9 +347,13 @@ export class EnvironmentStateExtraction { return; } if (found === true) continue; - names = (names ?? found.fields).filter((name) => - found.fields.includes(name), - ); + // The first recording's candidates stand; later ones intersect through a set, so a wide + // item costs one pass per recording. + if (names === undefined) names = found.fields; + else { + const matching = new Set(found.fields); + names = names.filter((name) => matching.has(name)); + } if (found.several) for (const name of found.fields) shown.add(name); } // An identity name is only inferred from items that carry it; empty lists prove none.