diff options
| author | adamelmore <[email protected]> | 2026-01-27 14:51:34 -0600 |
|---|---|---|
| committer | adamelmore <[email protected]> | 2026-01-27 15:25:07 -0600 |
| commit | 842f17d6d97c52d1efac66a8dca298f6ca692a56 (patch) | |
| tree | fd45e06f014dc5a7e72e509bb46f4c3ec1fb444c /packages/app/src/pages | |
| parent | 1ebf63c70c552c95794325f40bbd278ba3e0c725 (diff) | |
| download | opencode-842f17d6d97c52d1efac66a8dca298f6ca692a56.tar.gz opencode-842f17d6d97c52d1efac66a8dca298f6ca692a56.zip | |
perf(app): better memory management
Diffstat (limited to 'packages/app/src/pages')
| -rw-r--r-- | packages/app/src/pages/layout.tsx | 50 |
1 files changed, 48 insertions, 2 deletions
diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx index 82a3fa6c9..1328b96be 100644 --- a/packages/app/src/pages/layout.tsx +++ b/packages/app/src/pages/layout.tsx @@ -685,12 +685,34 @@ export default function Layout(props: ParentProps) { running: number } - const prefetchChunk = 600 + const prefetchChunk = 200 const prefetchConcurrency = 1 const prefetchPendingLimit = 6 const prefetchToken = { value: 0 } const prefetchQueues = new Map<string, PrefetchQueue>() + const PREFETCH_MAX_SESSIONS_PER_DIR = 10 + const prefetchedByDir = new Map<string, Map<string, true>>() + + const lruFor = (directory: string) => { + const existing = prefetchedByDir.get(directory) + if (existing) return existing + const created = new Map<string, true>() + prefetchedByDir.set(directory, created) + return created + } + + const markPrefetched = (directory: string, sessionID: string) => { + const lru = lruFor(directory) + if (lru.has(sessionID)) lru.delete(sessionID) + lru.set(sessionID, true) + while (lru.size > PREFETCH_MAX_SESSIONS_PER_DIR) { + const oldest = lru.keys().next().value as string | undefined + if (!oldest) return + lru.delete(oldest) + } + } + createEffect(() => { params.dir globalSDK.url @@ -783,6 +805,11 @@ export default function Layout(props: ParentProps) { if (q.inflight.has(session.id)) return if (q.pendingSet.has(session.id)) return + const lru = lruFor(directory) + const known = lru.has(session.id) + if (!known && lru.size >= PREFETCH_MAX_SESSIONS_PER_DIR && priority !== "high") return + markPrefetched(directory, session.id) + if (priority === "high") q.pending.unshift(session.id) if (priority !== "high") q.pending.push(session.id) q.pendingSet.add(session.id) @@ -1669,6 +1696,22 @@ export default function Layout(props: ParentProps) { pendingRename: false, }) + const hoverPrefetch = { current: undefined as ReturnType<typeof setTimeout> | undefined } + const cancelHoverPrefetch = () => { + if (hoverPrefetch.current === undefined) return + clearTimeout(hoverPrefetch.current) + hoverPrefetch.current = undefined + } + const scheduleHoverPrefetch = () => { + if (hoverPrefetch.current !== undefined) return + hoverPrefetch.current = setTimeout(() => { + hoverPrefetch.current = undefined + prefetchSession(props.session) + }, 200) + } + + onCleanup(cancelHoverPrefetch) + const messageLabel = (message: Message) => { const parts = sessionStore.part[message.id] ?? [] const text = parts.find((part): part is TextPart => part?.type === "text" && !part.synthetic && !part.ignored) @@ -1679,7 +1722,10 @@ export default function Layout(props: ParentProps) { <A href={`${props.slug}/session/${props.session.id}`} class={`flex items-center justify-between gap-3 min-w-0 text-left w-full focus:outline-none transition-[padding] ${menu.open ? "pr-7" : ""} group-hover/session:pr-7 group-focus-within/session:pr-7 group-active/session:pr-7 ${props.dense ? "py-0.5" : "py-1"}`} - onMouseEnter={() => prefetchSession(props.session, "high")} + onPointerEnter={scheduleHoverPrefetch} + onPointerLeave={cancelHoverPrefetch} + onMouseEnter={scheduleHoverPrefetch} + onMouseLeave={cancelHoverPrefetch} onFocus={() => prefetchSession(props.session, "high")} onClick={() => { setState("hoverSession", undefined) |
