Merge pull request #72163 from NousResearch/bb/desktop-render-waste

perf(desktop): stop the statusbar re-rendering per streaming token
This commit is contained in:
brooklyn! 2026-07-26 15:18:57 -05:00 committed by GitHub
commit 8943c9958b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 64 additions and 8 deletions

View file

@ -12,6 +12,7 @@ import { useI18n } from '@/i18n'
import { Activity, AlertCircle, Clock, Command, FolderOpen, Globe, Hash, Loader2, Terminal } from '@/lib/icons'
import type { RuntimeReadinessResult } from '@/lib/runtime-readiness'
import { contextBarLabel, LiveDuration, usageContextLabel } from '@/lib/statusbar'
import { useStoreSelector } from '@/lib/use-session-slice'
import { cn } from '@/lib/utils'
import { copyFilePath, revealFile } from '@/store/file-actions'
import { revealFileInTree } from '@/store/layout'
@ -117,19 +118,30 @@ export function useStatusbarItems({
// tile makes the statusbar describe THAT session.
const focusedStoredSessionId = useStore($focusedStoredSessionId)
const focusedRuntimeId = useStore($focusedRuntimeId)
const focusedState = useStore($focusedSessionState)
// `$focusedSessionState` is a projection of `$sessionStates`, which is
// republished on EVERY message delta — tens of times a second during a turn.
// Only three fields are read off it here, so subscribing to the whole object
// re-ran this hook (and re-created all ~9 statusbar items) per token. Select
// each field individually so an unchanged readout bails out instead.
const focusedBusy = useStoreSelector($focusedSessionState, state => Boolean(state?.busy))
const focusedTurnStartedAt = useStoreSelector($focusedSessionState, state => state?.turnStartedAt ?? null)
// `usage` is an object, so it can't be compared as a scalar. It IS however
// replaced wholesale rather than mutated, and only changes when the backend
// reports new usage — far rarer than a delta — so its reference is a valid
// bail-out key on its own.
const focusedUsage = useStoreSelector($focusedSessionState, state => state?.usage ?? null)
const sessions = useStore($sessions)
const selectedStoredSessionId = useStore($selectedStoredSessionId)
const primaryFocused = !focusedStoredSessionId || focusedStoredSessionId === selectedStoredSessionId
const activeSessionId = primaryFocused ? primaryActiveSessionId : (focusedRuntimeId ?? null)
const busy = primaryFocused ? primaryBusy : Boolean(focusedState?.busy)
const busy = primaryFocused ? primaryBusy : focusedBusy
// EMPTY_USAGE (module constant) keeps the fallback referentially stable —
// a fresh `{...}` each render would bust the usage-label memos below.
const currentUsage = primaryFocused ? primaryUsage : (focusedState?.usage ?? EMPTY_USAGE)
const currentUsage = primaryFocused ? primaryUsage : (focusedUsage ?? EMPTY_USAGE)
const turnStartedAt = primaryFocused ? primaryTurnStartedAt : (focusedState?.turnStartedAt ?? null)
const turnStartedAt = primaryFocused ? primaryTurnStartedAt : focusedTurnStartedAt
// A tile's session-start comes from its stored row (the cache only knows
// runtime state); seconds → ms.

View file

@ -1,4 +1,4 @@
import { type ComponentProps, type ReactNode, useState } from 'react'
import { type ComponentProps, memo, type ReactNode, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'
@ -95,7 +95,19 @@ export function StatusbarControls({ className, leftItems = [], items = [], ...pr
)
}
function StatusbarItemView({ item, navigate }: { item: StatusbarItem; navigate: ReturnType<typeof useNavigate> }) {
/** Memoized: `useStatusbarItems` rebuilds the item array whenever ANY of its
* inputs change, but each individual item object is usually identical across
* those rebuilds. Without this, one changed item (the running timer, say)
* re-rendered every other item in the bar measured at 1,446 wasted renders
* of 2,174 during a five-tab streaming run. `navigate` is stable for the
* router's lifetime, so item identity is the only real input. */
const StatusbarItemView = memo(function StatusbarItemView({
item,
navigate
}: {
item: StatusbarItem
navigate: ReturnType<typeof useNavigate>
}) {
const [menuOpen, setMenuOpen] = useState(false)
// Render escape hatch: the contribution owns its own chrome/state/tooltip.
@ -230,4 +242,4 @@ function StatusbarItemView({ item, navigate }: { item: StatusbarItem; navigate:
</button>
</Tip>
)
}
})

View file

@ -1,4 +1,4 @@
import { useSyncExternalStore } from 'react'
import { useCallback, useRef, useSyncExternalStore } from 'react'
interface SliceStore<T> {
get(): Record<string, T[] | undefined>
@ -29,3 +29,35 @@ export function useSessionSlice<T>(store: SliceStore<T>, key: string | null): T[
() => (key ? (store.get()[key] ?? (EMPTY as unknown as T[])) : (EMPTY as unknown as T[]))
)
}
interface ReadableStore<T> {
get(): T
listen(listener: () => void): () => void
}
/**
* Subscribe to a SCALAR derived from a hot store, re-rendering only when that
* scalar changes by `Object.is` not on every write to the store it came from.
*
* `useStore($someHotStore)` bails out on reference equality alone, so a store
* republished per streaming token re-renders every consumer even when the two
* or three fields they actually read are identical. `$sessionStates` is the
* canonical case: it is republished on every message delta, so a component
* reading only `busy` or `turnStartedAt` off it pays for the whole transcript's
* churn.
*
* `select` must return a PRIMITIVE (or a referentially stable value). Returning
* a fresh object or array defeats the bail-out and reintroduces the churn this
* exists to remove derive one scalar per call instead.
*/
export function useStoreSelector<T, S>(store: ReadableStore<T>, select: (value: T) => S): S {
// `select` is read through a ref so an inline arrow at the call site doesn't
// resubscribe on every render; useSyncExternalStore re-reads the snapshot on
// each render anyway, so the latest selector is always applied.
const selectRef = useRef(select)
selectRef.current = select
const subscribe = useCallback((onChange: () => void) => store.listen(onChange), [store])
return useSyncExternalStore(subscribe, () => selectRef.current(store.get()))
}