Incognito-per-render forfeits Chrome's V8 code cache (~9% CPU measured); parked on isolation at concurrency
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 35/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- javascript
- Lĩnh vực
- backend, performance
Hướng nghiên cứu
Start with bench/render-cpu/README and its harness, then inspect settings.browserExpirationThreshold, resetForNextVariant, and variantContext.ts for the existing retirement and wipe semantics. Measure 200–300 sequential renders with the fresh-incognito control, recording wall time, CPU, ScriptDuration, RSS, and process count, plus realistic per-slot resource use. Done means a reported series that attributes any aging and establishes whether per-slot persistent profiles are safe to pursue.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
What is true today
Every render gets a fresh incognito BrowserContext (settings.incognitoPages, default true; ManagedBrowser.getPage). An off-the-record context's HTTP cache is in-memory and dies with the context, and Chrome's V8 code cache lives in the disk-cache backend — so no compiled script ever survives a render. Two consequences:
--disk-cache-size=1073741824inDEFAULT_CHROME_ARGShas never applied to a single render.- A sub-resource replayed from our own
ResourceCacheviaFetch.fulfillRequestnever enters Chrome's HTTP cache either, so it can never get a code-cache entry. Our cache saves the fetch and forfeits the compile.
Every script on every page is therefore parsed and compiled from scratch, every render.
What it is worth
Measured on a live commerce product page, 6 renders per arm, interleaved, medians excluding the cold first render:
| arm | wall | CPU | ScriptDuration |
|---|---|---|---|
| incognito context per render (today) | 4,197ms | 4,900ms | 808ms |
default context + persistent userDataDir |
3,845 (−8%) | 4,440 (−9%) | 629 (−22%) |
| persistent profile + per-render wipe | 3,749 (−11%) | 4,450 (−9%) | 581 (−28%) |
Content identical in every arm (review nodes 1,430; zero un-hydrated framework islands; HTTP 200).
A synthetic fixture cannot size this — it reports ScriptDuration of ~40ms in a 7,500ms render, and V8CompileDuration is useless as an instrument because V8 compiles lazily on background threads. The win scales with a real page's script cost (measured 800–2,465ms on real pages), so only a real-page measurement decides it.
Why this is parked rather than shipped
The arm that was measured cannot ship. It ran at maxActivePages: 1 — strictly sequential — with incognitoPages: false, meaning every render shared the default context's single cookie jar. At production concurrency that breaks in two ways:
- Identity bleed across unrelated URLs. Concurrent renders of different pages interleave session, visitor and bot-mitigation cookies. This repo already measured the sibling case: an unwiped shared context handed a second device variant 125 cookies instead of the 6 pinned ones, putting both devices on one session id, one visitor id and one bot-mitigation token (see the v1.28.0 context-sharing work and
variantContext.ts). That is why context sharing only ever shipped scoped to one job, with a mandatory wipe and a fail-closed fallback. - The wipe is globally destructive.
deleteCookie+Storage.clearDataForOriginact on the whole context, so firing it between renders would delete the cookies of renders still in flight. Structural, not a tunable race.
The shape that could ship
One browser per slot, each with its own --user-data-dir — not a shared context. Each slot then has its own cookie jar (isolation exactly as today), its own disk cache (so the code cache warms), and renders within a slot are sequential by construction, which is the condition resetForNextVariant was designed for. It is the existing per-job argument, one level up.
Already settled, so nobody re-derives it
- The wipe is not a cost. Measured on live pages with all cookies deleted each time: 2–5ms against a ~4,000ms render (~0.1%), on a jar holding 48–77 cookies. The jar does not accumulate, because the wipe runs every render. (Puppeteer issues one
Network.deleteCookiesper cookie and 75 of them still lands in single-digit ms.) - Memory is not the constraint. Production pods have ample memory and disk. RSS is ~265MB per concurrent slot and linear, and extra browser processes cost 7–14% more RSS — worth reporting, not disqualifying.
Storage.clearDataForOrigindoes not clear the HTTP disk cache, which is why the wiped arm kept the whole win. Isolation and the code cache are not in tension.
What has to be measured before picking this up
- Does browser aging justify retiring at 200 pages? (
settings.browserExpirationThreshold) Retirement every ~13 minutes is exactly what would discard the warm profile. The reason on record is a general "prevent memory leaks" recommendation plus an operator observation that aged browsers seemed slower; it has never been measured. Wanted: an aging curve over 200–300 sequential renders (per-render wall, CPU, ScriptDuration, RSS, process count) reported as a series, with today's fresh-incognito shape as the control, and attribution if drift appears — is it RSS-correlated, renderer-process-age-correlated, or reset by disposing a context while keeping the browser? Only one of those is a thing retirement actually fixes. - Cookie semantics across job boundaries. Inside a slot, consecutive renders are different URLs, so the wipe must delete all cookies including the pinned ones — pins are job-scoped by design. That is a different wipe than the one that exists.
- Per-slot RSS and process count at realistic concurrency, for sizing rather than as a blocker.
Related
Our ResourceCache deserves a look in the same pass: measured at production resource counts it does not remove CPU, it moves ~50ms onto the single Node thread to save ~70ms of Chrome CPU, and Chrome's own cache achieves the same origin offload at zero Node cost — though only within one browser's lifetime, whereas the disk cache is shared across slots and restarts. That trade is only justified by real origin RTT, which a localhost fixture cannot price.
Bench harness and full numbers: bench/render-cpu/ (README has the method, the instruments, and the dead-end table).
- Ngôn ngữ chính
- JavaScript
- Star
- 0
- Fork
- 0
- Merge trung bình
- 8 giờ 25 phút
- Pull request đã merge (30 ngày)
- 71
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của HarperFast/prerender-plugin
-
enhancement
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 25/100
HarperFast/prerender-plugin#244 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
enhancement
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 30/100
HarperFast/prerender-plugin#242 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
enhancement performance
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 38/100
HarperFast/prerender-plugin#235 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
enhancement performance
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 38/100
HarperFast/prerender-plugin#233 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 74/100
HarperFast/prerender-plugin#218 ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của HarperFast/prerender-plugin
Issue tương tự
-
bug user-priority/P2
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 92/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 Dưới một giờ Mức phù hợp với người mới 78/100
opencart/opencart#15763 · 2 bình luận · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
neondatabase/agent-skills#139 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
Effect-TS/effect#8881 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
mail processing verified
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
Maintainer thường phản hồi trong vòng 7 ngày