perf(renderer): cache startup action selector (#17458)

This commit is contained in:
Neil
2026-08-30 23:04:37 -07:00
committed by GitHub
parent 8e132880be
commit fb271f2f3b
3 changed files with 199 additions and 33 deletions
@@ -0,0 +1,91 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { createStore } from 'zustand/vanilla'
import {
resetStartupActionsSelectorCacheForTest,
selectStartupActions,
type StartupActions
} from './startup-actions-selector'
type StartupTestState = StartupActions & { publication: number }
function makeActions(): StartupActions {
return {
fetchReposForAllHosts: vi.fn(),
awaitLocalRepoCatalogSettlement: vi.fn(),
fetchProjectGroupsForAllHosts: vi.fn(),
fetchFolderWorkspacesForAllHosts: vi.fn(),
fetchAllWorktrees: vi.fn(),
fetchWorktrees: vi.fn(),
fetchWorktreeLineage: vi.fn(),
fetchOrcaProfiles: vi.fn(),
fetchSettings: vi.fn(),
awaitOwnerWorktreeVisibilityDefaultsHydration: vi.fn(),
fetchKeybindings: vi.fn(),
initGitHubCache: vi.fn(),
hydrateWorkspaceSession: vi.fn(),
hydrateTabsSession: vi.fn(),
hydrateEditorSession: vi.fn(),
hydrateBrowserSession: vi.fn(),
fetchBrowserSessionProfiles: vi.fn(),
reconnectPersistedTerminals: vi.fn(),
setTerminalStartupRestorationReady: vi.fn(),
setDeferredSshReconnectTargets: vi.fn(),
setSshConnectionState: vi.fn(),
hydratePersistedUI: vi.fn(),
setHydrationSucceeded: vi.fn(),
pruneLastVisitedTimestamps: vi.fn(),
seedActiveWorktreeLastVisitedIfMissing: vi.fn()
} as StartupActions
}
describe('startup action selector', () => {
beforeEach(() => {
resetStartupActionsSelectorCacheForTest()
})
it('reuses one action bundle across 1,000 repeated reads', () => {
const actions = makeActions()
const first = selectStartupActions(actions)
for (let read = 0; read < 1_000; read += 1) {
expect(selectStartupActions(actions)).toBe(first)
}
})
it('rebuilds the bundle when one action reference changes', () => {
const actions = makeActions()
const first = selectStartupActions(actions)
const replacement = { ...actions, fetchSettings: vi.fn() } as StartupActions
const next = selectStartupActions(replacement)
expect(next).not.toBe(first)
for (let read = 0; read < 1_000; read += 1) {
expect(selectStartupActions(replacement)).toBe(next)
}
})
it('keeps the selected projection stable across 1,000 unrelated publications', () => {
const actions = makeActions()
const store = createStore<StartupTestState>(() => ({ ...actions, publication: 0 }))
let publicationCount = 0
let projectionChangeCount = 0
let previousProjection = selectStartupActions(store.getState())
const unsubscribe = store.subscribe((state) => {
publicationCount += 1
const projection = selectStartupActions(state)
if (projection !== previousProjection) {
projectionChangeCount += 1
}
previousProjection = projection
})
for (let publication = 1; publication <= 1_000; publication += 1) {
store.setState({ publication })
}
expect(publicationCount).toBe(1_000)
expect(projectionChangeCount).toBe(0)
unsubscribe()
})
})
@@ -0,0 +1,105 @@
import type { AppState } from '../store/types'
export type StartupActions = Pick<
AppState,
| 'fetchReposForAllHosts'
| 'awaitLocalRepoCatalogSettlement'
| 'fetchProjectGroupsForAllHosts'
| 'fetchFolderWorkspacesForAllHosts'
| 'fetchAllWorktrees'
| 'fetchWorktrees'
| 'fetchWorktreeLineage'
| 'fetchOrcaProfiles'
| 'fetchSettings'
| 'awaitOwnerWorktreeVisibilityDefaultsHydration'
| 'fetchKeybindings'
| 'initGitHubCache'
| 'hydrateWorkspaceSession'
| 'hydrateTabsSession'
| 'hydrateEditorSession'
| 'hydrateBrowserSession'
| 'fetchBrowserSessionProfiles'
| 'reconnectPersistedTerminals'
| 'setTerminalStartupRestorationReady'
| 'setDeferredSshReconnectTargets'
| 'setSshConnectionState'
| 'hydratePersistedUI'
| 'setHydrationSucceeded'
| 'pruneLastVisitedTimestamps'
| 'seedActiveWorktreeLastVisitedIfMissing'
>
let cachedStartupActions: StartupActions | null = null
/** Keeps the always-mounted startup subscription stable across unrelated store writes. */
export function selectStartupActions(state: StartupActions): StartupActions {
if (
cachedStartupActions &&
cachedStartupActions.fetchReposForAllHosts === state.fetchReposForAllHosts &&
cachedStartupActions.awaitLocalRepoCatalogSettlement ===
state.awaitLocalRepoCatalogSettlement &&
cachedStartupActions.fetchProjectGroupsForAllHosts === state.fetchProjectGroupsForAllHosts &&
cachedStartupActions.fetchFolderWorkspacesForAllHosts ===
state.fetchFolderWorkspacesForAllHosts &&
cachedStartupActions.fetchAllWorktrees === state.fetchAllWorktrees &&
cachedStartupActions.fetchWorktrees === state.fetchWorktrees &&
cachedStartupActions.fetchWorktreeLineage === state.fetchWorktreeLineage &&
cachedStartupActions.fetchOrcaProfiles === state.fetchOrcaProfiles &&
cachedStartupActions.fetchSettings === state.fetchSettings &&
cachedStartupActions.awaitOwnerWorktreeVisibilityDefaultsHydration ===
state.awaitOwnerWorktreeVisibilityDefaultsHydration &&
cachedStartupActions.fetchKeybindings === state.fetchKeybindings &&
cachedStartupActions.initGitHubCache === state.initGitHubCache &&
cachedStartupActions.hydrateWorkspaceSession === state.hydrateWorkspaceSession &&
cachedStartupActions.hydrateTabsSession === state.hydrateTabsSession &&
cachedStartupActions.hydrateEditorSession === state.hydrateEditorSession &&
cachedStartupActions.hydrateBrowserSession === state.hydrateBrowserSession &&
cachedStartupActions.fetchBrowserSessionProfiles === state.fetchBrowserSessionProfiles &&
cachedStartupActions.reconnectPersistedTerminals === state.reconnectPersistedTerminals &&
cachedStartupActions.setTerminalStartupRestorationReady ===
state.setTerminalStartupRestorationReady &&
cachedStartupActions.setDeferredSshReconnectTargets === state.setDeferredSshReconnectTargets &&
cachedStartupActions.setSshConnectionState === state.setSshConnectionState &&
cachedStartupActions.hydratePersistedUI === state.hydratePersistedUI &&
cachedStartupActions.setHydrationSucceeded === state.setHydrationSucceeded &&
cachedStartupActions.pruneLastVisitedTimestamps === state.pruneLastVisitedTimestamps &&
cachedStartupActions.seedActiveWorktreeLastVisitedIfMissing ===
state.seedActiveWorktreeLastVisitedIfMissing
) {
return cachedStartupActions
}
cachedStartupActions = {
fetchReposForAllHosts: state.fetchReposForAllHosts,
awaitLocalRepoCatalogSettlement: state.awaitLocalRepoCatalogSettlement,
fetchProjectGroupsForAllHosts: state.fetchProjectGroupsForAllHosts,
fetchFolderWorkspacesForAllHosts: state.fetchFolderWorkspacesForAllHosts,
fetchAllWorktrees: state.fetchAllWorktrees,
fetchWorktrees: state.fetchWorktrees,
fetchWorktreeLineage: state.fetchWorktreeLineage,
fetchOrcaProfiles: state.fetchOrcaProfiles,
fetchSettings: state.fetchSettings,
awaitOwnerWorktreeVisibilityDefaultsHydration:
state.awaitOwnerWorktreeVisibilityDefaultsHydration,
fetchKeybindings: state.fetchKeybindings,
initGitHubCache: state.initGitHubCache,
hydrateWorkspaceSession: state.hydrateWorkspaceSession,
hydrateTabsSession: state.hydrateTabsSession,
hydrateEditorSession: state.hydrateEditorSession,
hydrateBrowserSession: state.hydrateBrowserSession,
fetchBrowserSessionProfiles: state.fetchBrowserSessionProfiles,
reconnectPersistedTerminals: state.reconnectPersistedTerminals,
setTerminalStartupRestorationReady: state.setTerminalStartupRestorationReady,
setDeferredSshReconnectTargets: state.setDeferredSshReconnectTargets,
setSshConnectionState: state.setSshConnectionState,
hydratePersistedUI: state.hydratePersistedUI,
setHydrationSucceeded: state.setHydrationSucceeded,
pruneLastVisitedTimestamps: state.pruneLastVisitedTimestamps,
seedActiveWorktreeLastVisitedIfMissing: state.seedActiveWorktreeLastVisitedIfMissing
}
return cachedStartupActions
}
export function resetStartupActionsSelectorCacheForTest(): void {
cachedStartupActions = null
}
@@ -1,39 +1,9 @@
// The renderer boot chain's store subscription, kept apart from the chain itself
// so one useShallow equality check covers every startup action.
// so unrelated store publications reuse one action projection.
import { useShallow } from 'zustand/react/shallow'
import { useAppStore } from '../store'
import { selectStartupActions } from './startup-actions-selector'
export function useStartupActions() {
// Why: consolidate action refs into one useShallow subscription so React runs one equality check per store mutation instead of one per action.
return useAppStore(
useShallow((s) => ({
fetchReposForAllHosts: s.fetchReposForAllHosts,
awaitLocalRepoCatalogSettlement: s.awaitLocalRepoCatalogSettlement,
fetchProjectGroupsForAllHosts: s.fetchProjectGroupsForAllHosts,
fetchFolderWorkspacesForAllHosts: s.fetchFolderWorkspacesForAllHosts,
fetchAllWorktrees: s.fetchAllWorktrees,
fetchWorktrees: s.fetchWorktrees,
fetchWorktreeLineage: s.fetchWorktreeLineage,
fetchOrcaProfiles: s.fetchOrcaProfiles,
fetchSettings: s.fetchSettings,
awaitOwnerWorktreeVisibilityDefaultsHydration:
s.awaitOwnerWorktreeVisibilityDefaultsHydration,
fetchKeybindings: s.fetchKeybindings,
initGitHubCache: s.initGitHubCache,
hydrateWorkspaceSession: s.hydrateWorkspaceSession,
hydrateTabsSession: s.hydrateTabsSession,
hydrateEditorSession: s.hydrateEditorSession,
hydrateBrowserSession: s.hydrateBrowserSession,
fetchBrowserSessionProfiles: s.fetchBrowserSessionProfiles,
reconnectPersistedTerminals: s.reconnectPersistedTerminals,
setTerminalStartupRestorationReady: s.setTerminalStartupRestorationReady,
setDeferredSshReconnectTargets: s.setDeferredSshReconnectTargets,
setSshConnectionState: s.setSshConnectionState,
hydratePersistedUI: s.hydratePersistedUI,
setHydrationSucceeded: s.setHydrationSucceeded,
pruneLastVisitedTimestamps: s.pruneLastVisitedTimestamps,
seedActiveWorktreeLastVisitedIfMissing: s.seedActiveWorktreeLastVisitedIfMissing
}))
)
return useAppStore(selectStartupActions)
}