From 900fce25cdfffc17291efc62b5ac3bec22849334 Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Sun, 30 Aug 2026 23:05:28 -0700 Subject: [PATCH] perf(renderer): cache active terminal chrome projection (#17480) --- .../active-terminal-chrome-selector.test.ts | 115 ++++++++++++++++++ .../store/active-terminal-chrome-selector.ts | 38 ++++-- 2 files changed, 146 insertions(+), 7 deletions(-) create mode 100644 src/renderer/src/store/active-terminal-chrome-selector.test.ts diff --git a/src/renderer/src/store/active-terminal-chrome-selector.test.ts b/src/renderer/src/store/active-terminal-chrome-selector.test.ts new file mode 100644 index 00000000000..b4d631000ee --- /dev/null +++ b/src/renderer/src/store/active-terminal-chrome-selector.test.ts @@ -0,0 +1,115 @@ +import { beforeEach, describe, expect, it } from 'vitest' +import type { TerminalTab } from '../../../shared/terminal-tab-types' +import { + resetActiveTerminalChromeStateSelectorCacheForTest, + selectActiveTerminalChromeState +} from './active-terminal-chrome-selector' + +function terminalTab(id: string, worktreeId = 'wt-1'): TerminalTab { + return { + id, + ptyId: null, + worktreeId, + title: id, + customTitle: null, + color: null, + sortOrder: 0, + createdAt: 1 + } +} + +describe('selectActiveTerminalChromeState', () => { + beforeEach(() => { + resetActiveTerminalChromeStateSelectorCacheForTest() + }) + + it('reuses the projection for stable inputs across selector fanout', () => { + const tabs = [terminalTab('tab-1')] + const state = { + activeWorktreeId: 'wt-1', + activeTabId: 'tab-1', + tabsByWorktree: { 'wt-1': tabs }, + canExpandPaneByTabId: { 'tab-1': true }, + expandedPaneByTabId: { 'tab-1': false } + } satisfies Parameters[0] + + const first = selectActiveTerminalChromeState(state) + let distinctResults = 0 + let previous = first + const iterations = 100_000 + for (let index = 0; index < iterations; index += 1) { + const selected = selectActiveTerminalChromeState(state) + if (selected !== previous) { + distinctResults += 1 + } + previous = selected + } + + expect(distinctResults).toBe(0) + expect(previous).toBe(first) + }) + + it('reuses equivalent replacement inputs and invalidates visible scalar changes', () => { + const tabs = [terminalTab('tab-1')] + const state = { + activeWorktreeId: 'wt-1', + activeTabId: null, + tabsByWorktree: { 'wt-1': tabs }, + canExpandPaneByTabId: { 'tab-1': false }, + expandedPaneByTabId: { 'tab-1': false } + } satisfies Parameters[0] + + const first = selectActiveTerminalChromeState(state) + const equivalentReplacement = selectActiveTerminalChromeState({ + ...state, + tabsByWorktree: { 'wt-1': tabs.map((tab) => ({ ...tab, title: 'new title' })) }, + canExpandPaneByTabId: { 'tab-1': false }, + expandedPaneByTabId: { 'tab-1': false } + }) + expect(equivalentReplacement).toBe(first) + + const afterActiveTabId = selectActiveTerminalChromeState({ + ...state, + activeTabId: 'tab-1' + }) + expect(afterActiveTabId).not.toBe(first) + + const afterActiveWorktreeId = selectActiveTerminalChromeState({ + ...state, + activeWorktreeId: 'wt-2', + tabsByWorktree: { 'wt-2': tabs } + }) + expect(afterActiveWorktreeId).not.toBe(afterActiveTabId) + + const afterEffectiveActiveTabId = selectActiveTerminalChromeState({ + ...state, + tabsByWorktree: { 'wt-1': [terminalTab('tab-2')] } + }) + expect(afterEffectiveActiveTabId).not.toBe(afterActiveWorktreeId) + expect(afterEffectiveActiveTabId.effectiveActiveTabId).toBe('tab-2') + + const afterCanExpand = selectActiveTerminalChromeState({ + ...state, + canExpandPaneByTabId: { 'tab-1': true } + }) + expect(afterCanExpand).not.toBe(afterEffectiveActiveTabId) + expect(afterCanExpand.activeTabCanExpand).toBe(true) + + const afterExpanded = selectActiveTerminalChromeState({ + ...state, + canExpandPaneByTabId: { 'tab-1': true }, + expandedPaneByTabId: { 'tab-1': true } + }) + expect(afterExpanded).not.toBe(afterCanExpand) + expect(afterExpanded.effectiveActiveTabExpanded).toBe(true) + + const afterTabCount = selectActiveTerminalChromeState({ + ...state, + tabsByWorktree: { + 'wt-1': [...tabs, terminalTab('tab-2')] + } + }) + expect(afterTabCount).not.toBe(afterExpanded) + expect(afterTabCount.tabCount).toBe(2) + }) +}) diff --git a/src/renderer/src/store/active-terminal-chrome-selector.ts b/src/renderer/src/store/active-terminal-chrome-selector.ts index f886fc4ec40..b78952937b9 100644 --- a/src/renderer/src/store/active-terminal-chrome-selector.ts +++ b/src/renderer/src/store/active-terminal-chrome-selector.ts @@ -20,6 +20,9 @@ export type ActiveTerminalChromeState = { const EMPTY_TABS: NonNullable = [] +// Why: every Zustand write reruns this app-shell selector, including title-only tab updates. +let activeTerminalChromeCache: ActiveTerminalChromeState | null = null + export function selectActiveTerminalChromeState( state: ActiveTerminalChromeSelectorState ): ActiveTerminalChromeState { @@ -27,16 +30,37 @@ export function selectActiveTerminalChromeState( ? (state.tabsByWorktree[state.activeWorktreeId] ?? EMPTY_TABS) : EMPTY_TABS const effectiveActiveTabId = state.activeTabId ?? tabs[0]?.id ?? null - return { + const activeTabCanExpand = effectiveActiveTabId + ? (state.canExpandPaneByTabId[effectiveActiveTabId] ?? false) + : false + const effectiveActiveTabExpanded = effectiveActiveTabId + ? (state.expandedPaneByTabId[effectiveActiveTabId] ?? false) + : false + const cached = activeTerminalChromeCache + if ( + cached && + cached.activeWorktreeId === state.activeWorktreeId && + cached.activeTabId === state.activeTabId && + cached.tabCount === tabs.length && + cached.effectiveActiveTabId === effectiveActiveTabId && + cached.activeTabCanExpand === activeTabCanExpand && + cached.effectiveActiveTabExpanded === effectiveActiveTabExpanded + ) { + return cached + } + + const selected: ActiveTerminalChromeState = { activeWorktreeId: state.activeWorktreeId, activeTabId: state.activeTabId, tabCount: tabs.length, effectiveActiveTabId, - activeTabCanExpand: effectiveActiveTabId - ? (state.canExpandPaneByTabId[effectiveActiveTabId] ?? false) - : false, - effectiveActiveTabExpanded: effectiveActiveTabId - ? (state.expandedPaneByTabId[effectiveActiveTabId] ?? false) - : false + activeTabCanExpand, + effectiveActiveTabExpanded } + activeTerminalChromeCache = selected + return selected +} + +export function resetActiveTerminalChromeStateSelectorCacheForTest(): void { + activeTerminalChromeCache = null }