Skip to content

fix(desktop): sweep React dev user-timing measures to stop WebKit memory growth - #7815

Open
Giszmo wants to merge 1 commit into
block:mainfrom
Giszmo:fix/dev-user-timing-sweep
Open

Giszmo wants to merge 1 commit into
block:mainfrom
Giszmo:fix/dev-user-timing-sweep

Conversation

@Giszmo

@Giszmo Giszmo commented Sep 22, 2026

Copy link
Copy Markdown

Problem

tauri dev sessions on Linux grow by tens of MB per minute while idle until WebKitWebProcess is OOM-killed (13 GB anon RSS overnight, see #6272 for an earlier report). Release builds of the same commit stay flat.

Cause

React 19's development bundle records a performance.measure() entry with a serialized detail object for every component render (its "Components ⚛" DevTools track). WebKit keeps user-timing entries for the life of the page, outside the JavaScript heap, so nothing GC can free them. An idle dev session with one channel open held 185,974 measures after 17 minutes; heaptrack with WebKit debug symbols attributed the retained memory to PerformanceUserTiming::measure → SerializedScriptValue::create. The DOM, CSS rule count and JS heap were flat the whole time. The production bundle never emits these entries.

Fix

Clear the measure buffer every 10 s in dev builds (startUserTimingSweep, wired in main.tsx under import.meta.env.DEV). Nothing reads a measure later: the sidebar boot measure in features/channels/hooks.ts reads its own entry synchronously. Marks are untouched; React does not accumulate those.

Verification

Same commit, same machine, tauri dev with #buzz open, WebKitWebProcess RSS sampled every 10 s:

2 min 7 min 12 min retained measures
before 1039 MB 1317 MB (killed at 5 GB after 32 min on another box) 185,974 at 17 min
after 1017 MB 1004 MB 1004 MB 0 between sweeps

pnpm typecheck, biome check, and pnpm test (6584 tests) pass.

🤖 Generated with Claude Code

@Giszmo
Giszmo requested a review from a team as a code owner September 22, 2026 21:44
@github-actions

github-actions Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

🔐 Codex Security Review

Status: review required for the current range.

The current range is 326e2301cb4b1edcb8a72d01ac4b19a83545365f...4fd960d5dedebf40477bab09a163f26d11244d60.
A new review must complete for this exact range. When manual authorization
is required, a user with write access must comment exactly
@buzz-security-review 4fd960d5dedebf40477bab09a163f26d11244d60 to authorize a new review.
Any previous review applies only to its recorded range.

@Giszmo
Giszmo force-pushed the fix/dev-user-timing-sweep branch from 0e72af3 to d685350 Compare September 22, 2026 21:45
…ory growth

React 19's development bundle records a performance.measure() entry with a
serialized detail object for every component render (its "Components ⚛"
DevTools track). WebKit keeps user-timing entries for the life of the page,
outside the JavaScript heap, so a `tauri dev` session grows by tens of MB per
minute while idle until WebKitWebProcess is OOM-killed. The production bundle
never emits these entries, which is why release builds stay flat.

Clear the measure buffer every 10 s in dev builds. Nothing reads a measure
later; the sidebar boot measure reads its own entry synchronously.

Fable 5.1 helped authoring this commit.

Signed-off-by: Leo Wandersleb <leo@leowandersleb.de>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant