From 7d7a3ffeb6593a9c7205ac9db7bcf3aa2e4bf58e Mon Sep 17 00:00:00 2001 From: Jinwoo-H Date: Thu, 27 Aug 2026 06:34:41 -0400 Subject: [PATCH] perf(cmd-j): delete cold indexing work --- .../src/components/WorktreeJumpPalette.tsx | 12 +++-- .../src/lib/palette-match/indexed-field.ts | 46 ------------------- .../src/lib/palette-match/match-field.ts | 33 ++++++------- tests/e2e/cmd-j-cold-open-performance.spec.ts | 2 +- 4 files changed, 23 insertions(+), 70 deletions(-) diff --git a/src/renderer/src/components/WorktreeJumpPalette.tsx b/src/renderer/src/components/WorktreeJumpPalette.tsx index 4902f5a8319..7d14f567f21 100644 --- a/src/renderer/src/components/WorktreeJumpPalette.tsx +++ b/src/renderer/src/components/WorktreeJumpPalette.tsx @@ -1355,7 +1355,10 @@ function WorktreeJumpPaletteContent({ ) const worktreeItems = useMemo(() => { - const items = worktreeMatches + const matches = hasQuery + ? worktreeMatches + : worktreeMatches.slice(0, EMPTY_QUERY_ROW_BUDGET + (expandedSectionCaps['worktrees'] ?? 0)) + const items = matches .map((match) => { const worktree = resolveWorktree(match.worktreeId, match.worktreeHostId) if (!worktree) { @@ -1384,7 +1387,7 @@ function WorktreeJumpPaletteContent({ { rank: b.match.rank, order: orderById.get(b.id) ?? 0, id: b.id } ) ) - }, [hasQuery, resolveWorktree, worktreeMatches]) + }, [expandedSectionCaps, hasQuery, resolveWorktree, worktreeMatches]) const browserItems = useMemo( () => @@ -1899,7 +1902,7 @@ function WorktreeJumpPaletteContent({ ? capPaletteSection(worktreeItems, worktreeCap) : { visible: worktreeItems.slice(0, worktreeCap), - overflowCount: Math.max(0, worktreeItems.length - worktreeCap) + overflowCount: Math.max(0, worktreeMatches.length - worktreeCap) } const projectTargetsCap = PALETTE_SECTION_RENDER_CAP + (expandedSectionCaps['projects'] ?? 0) const projectTargets = capPaletteSection(hasQuery ? projectTargetItems : [], projectTargetsCap) @@ -1941,7 +1944,8 @@ function WorktreeJumpPaletteContent({ openTabItems, recentTabItems, hasQuery, - openTabsLeadSections + openTabsLeadSections, + worktreeMatches.length ]) // Why: badges number the snapshotted recent rows only — ⌘N is meaningless on a typed query. diff --git a/src/renderer/src/lib/palette-match/indexed-field.ts b/src/renderer/src/lib/palette-match/indexed-field.ts index b4a101a7d01..0e87ae37895 100644 --- a/src/renderer/src/lib/palette-match/indexed-field.ts +++ b/src/renderer/src/lib/palette-match/indexed-field.ts @@ -1,5 +1,4 @@ import { normalizePaletteText, type NormalizedText } from './normalized-text' -import { isLetterOnlyWord } from './palette-query' import { segmentPaletteText, type PaletteAtom, type PaletteWord } from './text-segments' import type { PaletteMatchQuality } from './match-quality' @@ -41,46 +40,11 @@ export type PaletteIndexedField = { text: NormalizedText atoms: readonly PaletteAtom[] words: readonly PaletteWord[] - firstAtomByText: ReadonlyMap - firstWordByText: ReadonlyMap - uniqueAtoms: readonly PaletteAtom[] - uniqueWords: readonly PaletteWord[] - wordStarts: ReadonlySet - typoWordsByLength: ReadonlyMap evidenceId: string | null identifier: PaletteIdentifierOptions | null isContainer: boolean } -function indexFirstByText(entries: readonly T[], textOf: (entry: T) => string): Map { - const firstByText = new Map() - for (const entry of entries) { - const text = textOf(entry) - if (!firstByText.has(text)) { - firstByText.set(text, entry) - } - } - return firstByText -} - -function indexTypoWordsByLength(words: readonly PaletteWord[]): Map { - const byLength = new Map() - const seen = new Set() - for (const word of words) { - if (word.text.length < 4 || !isLetterOnlyWord(word.text) || seen.has(word.text)) { - continue - } - seen.add(word.text) - const bucket = byLength.get(word.text.length) - if (bucket) { - bucket.push(word) - } else { - byLength.set(word.text.length, [word]) - } - } - return byLength -} - const IDENTIFIER_PREFIX_KINDS: ReadonlySet = new Set([ 'port', 'sha', @@ -157,22 +121,12 @@ export function indexPaletteField(source: PaletteFieldSource): PaletteIndexedFie } const text = normalizePaletteText(trimmed) const segments = segmentPaletteText(text) - const firstAtomByText = indexFirstByText(segments.atoms, (atom) => - text.normalized.slice(atom.start, atom.end) - ) - const firstWordByText = indexFirstByText(segments.words, (word) => word.text) return { id: source.id, profile: source.profile, text, atoms: segments.atoms, words: segments.words, - firstAtomByText, - firstWordByText, - uniqueAtoms: [...firstAtomByText.values()], - uniqueWords: [...firstWordByText.values()], - wordStarts: new Set(segments.words.map((word) => word.start)), - typoWordsByLength: indexTypoWordsByLength(segments.words), evidenceId: source.evidenceId ?? null, identifier: source.identifier ?? null, isContainer: Boolean(source.isContainer) diff --git a/src/renderer/src/lib/palette-match/match-field.ts b/src/renderer/src/lib/palette-match/match-field.ts index 4bdbd302899..f9015ec49a5 100644 --- a/src/renderer/src/lib/palette-match/match-field.ts +++ b/src/renderer/src/lib/palette-match/match-field.ts @@ -4,9 +4,9 @@ import { paletteProfileAllowedQualities, type PaletteIndexedField } from './indexed-field' -import type { PaletteQueryToken } from './palette-query' +import { isLetterOnlyWord, type PaletteQueryToken } from './palette-query' import type { PaletteMatchQuality } from './match-quality' -import type { PaletteAtom, PaletteWord } from './text-segments' +import type { PaletteAtom } from './text-segments' import { isPaletteTypoCandidate, isWithinOnePaletteEdit } from './typo-distance' export type PaletteFieldMatch = { @@ -56,7 +56,7 @@ function passesSigilGate(field: PaletteIndexedField, token: PaletteQueryToken): } function isWordStart(field: PaletteIndexedField, index: number): boolean { - return field.wordStarts.has(index) || index === 0 + return field.words.some((word) => word.start === index) || index === 0 } function matchAtomComponentRun(atom: PaletteAtom, compact: string): [number, number] | null { @@ -92,11 +92,11 @@ function matchLiteral( return { quality: 'field-exact', ranges: toRanges(field, 0, normalized.length) } } if (qualities.has('word-exact')) { - const word = field.firstWordByText.get(text) + const word = field.words.find((entry) => entry.text === text) if (word) { return { quality: 'word-exact', ranges: toRanges(field, word.start, word.end) } } - const atom = field.firstAtomByText.get(text) + const atom = field.atoms.find((entry) => normalized.slice(entry.start, entry.end) === text) if (atom) { return { quality: 'word-exact', ranges: toRanges(field, atom.start, atom.end) } } @@ -105,8 +105,8 @@ function matchLiteral( return { quality: 'field-prefix', ranges: toRanges(field, 0, text.length) } } if (qualities.has('word-prefix')) { - const word = field.uniqueWords.find((entry) => entry.text.startsWith(text)) - const atom = field.uniqueAtoms.find((entry) => normalized.startsWith(text, entry.start)) + const word = field.words.find((entry) => entry.text.startsWith(text)) + const atom = field.atoms.find((entry) => normalized.startsWith(text, entry.start)) const start = word && atom ? Math.min(word.start, atom.start) : (word?.start ?? atom?.start) if (start !== undefined) { return { quality: 'word-prefix', ranges: toRanges(field, start, start + text.length) } @@ -157,20 +157,15 @@ function matchTypo( if (!qualities.has('typo') || !token.isLetterOnly || !isPaletteTypoCandidate(token.text)) { return null } - let firstMatch: PaletteWord | null = null - for (let length = token.text.length - 1; length <= token.text.length + 1; length += 1) { - for (const word of field.typoWordsByLength.get(length) ?? []) { - if ( - isWithinOnePaletteEdit(token.text, word.text) && - (!firstMatch || word.start < firstMatch.start) - ) { - firstMatch = word - } + for (const word of field.words) { + if (!isPaletteTypoCandidate(word.text) || !isLetterOnlyWord(word.text)) { + continue + } + if (isWithinOnePaletteEdit(token.text, word.text)) { + return { quality: 'typo', ranges: toRanges(field, word.start, word.end) } } } - return firstMatch - ? { quality: 'typo', ranges: toRanges(field, firstMatch.start, firstMatch.end) } - : null + return null } /** Best allowed match of one token against one field, or null when unmatched. */ diff --git a/tests/e2e/cmd-j-cold-open-performance.spec.ts b/tests/e2e/cmd-j-cold-open-performance.spec.ts index 3a4e79f7419..7e93666bb18 100644 --- a/tests/e2e/cmd-j-cold-open-performance.spec.ts +++ b/tests/e2e/cmd-j-cold-open-performance.spec.ts @@ -430,7 +430,7 @@ async function expectAccumulatedCatalogCompleteness(dialog: Locator): Promise rows.allTextContents()).toEqual(firstOrder) } function expectFrameSafe(metrics: InteractionMetrics): void {