summaryrefslogtreecommitdiffhomepage
path: root/packages/app/src/pages
diff options
context:
space:
mode:
authoradamelmore <[email protected]>2026-01-27 14:51:34 -0600
committeradamelmore <[email protected]>2026-01-27 15:25:07 -0600
commit842f17d6d97c52d1efac66a8dca298f6ca692a56 (patch)
treefd45e06f014dc5a7e72e509bb46f4c3ec1fb444c /packages/app/src/pages
parent1ebf63c70c552c95794325f40bbd278ba3e0c725 (diff)
downloadopencode-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.tsx50
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)