web browser (Servo)
git clone https://git.lucas.co/cce-browser.git
docs: Servo leaks a document per load, and what that cost
Recorded because it took the machine down today and because the obvious
fix is a dead end — both worth knowing before someone rediscovers them.
A page on a 1s reload loop grows RSS ~0.9 GB per 90s, linear, never
reclaimed. Isolated in a shadow session: the same page's JS churn without
the reload is flat, and cloudflare.com fully loaded and animating is flat.
Navigation leaks, script does not. Upstream in Servo; nothing to fix here.
What it cost: a Cloudflare interstitial re-runs itself waiting on a
browser-integrity check Servo can never pass, and reached 54 GB RSS in
about six minutes — 83% of a 62 GB box, memory PSI reporting full stall,
every process on the machine crawling. The reported symptom was "the page
seems unresponsive," which it was, along with everything else.
Ctrl+Shift+O is the escape hatch and now has a second reason to exist.
cce://downloads is the same hazard in our own code: it self-refreshes at
1s while a transfer runs, so watching a long download leaks at that rate.
The fix I wanted — poll a fragment and swap it in, no navigation — stops
the leak (0.00 GB over 60s, verified) but does not work: fetch() cannot
reach a cce: URL, with or without Access-Control-Allow-Origin, and the
page sat at "0 B..." while 41 MB landed on disk. The protocol registry
appears to serve top-level navigations only. Reverted rather than ship
live-looking progress that never updates; the note says so, so the next
attempt starts from a localhost endpoint or chrome-side progress instead
of repeating the experiment.
Co-Authored-By: Claude Opus 5 <[email protected]>
CLAUDE.md | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/CLAUDE.md b/CLAUDE.md
index 28e7494..2e59746 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -137,8 +137,29 @@ applies the inverted delta itself.
`cce://history`, `cce://bookmarks`, `cce://downloads` and `cce://cookies` are **real
pages fetched through Servo's network stack** and rendered like any other. That is why
every mutating action is an ordinary link (`cce://history/clear`,
-`cce://bookmarks/remove?url=…`) — no chrome plumbing needed, and the live downloads
-page just sets a 1 s `<meta refresh>` while transfers run.
+`cce://bookmarks/remove?url=…`) — no chrome plumbing needed.
+
+### Servo leaks a document per load — the biggest live hazard
+
+Measured 2026-08-27: a page on a 1 s reload loop grows RSS ~0.9 GB per 90 s, linear,
+never reclaimed. Isolated cleanly — the same page's JS churn *without* the reload is
+flat, and an animation-heavy real page (cloudflare.com fully loaded) is flat. It is
+navigation that leaks, not script. This is upstream in Servo and not fixable here.
+
+In the wild it took the whole machine down: a **Cloudflare interstitial**
+(`"Just a moment..."`) re-runs itself waiting on a browser-integrity check Servo can
+never pass, and reached **54 GB RSS in ~6 minutes** — 83% of a 62 GB box, everything
+stalling on reclaim. Ctrl+Shift+O (hand the page to another browser) is the escape
+hatch, and the reason it exists.
+
+**`cce://downloads` is the same hazard in our own code**: it carries
+`<meta http-equiv="refresh" content="1">` while any transfer is active, so watching a
+long download leaks at the rate above. Fixing it means live progress without a
+navigation, and the obvious route is closed — **`fetch()` cannot reach a `cce:` URL**
+(tried, including with `Access-Control-Allow-Origin: *`; the protocol registry appears
+to serve top-level navigations only, and the fetch just rejects). A fix needs either a
+real localhost HTTP endpoint the page can fetch, or progress moved into the chrome.
+Until then, don't add a self-refreshing `cce:` page, and know this one is live.
The handler runs on **Servo's fetch threads**, hence the `Arc<Mutex<_>>` stores. It
therefore *cannot reach Servo itself*: `cce://cookies/clear` sets an `AtomicBool` that