138 lines
8.5 KiB
Markdown
138 lines
8.5 KiB
Markdown
# Phase 6 investigation
|
|
|
|
All comparisons use the current instrumented harness with matching frontend and
|
|
server from detached worktrees beneath `perf/.tmp`. No production requests.
|
|
Command template (three fresh contexts):
|
|
|
|
```
|
|
node perf/baseline.mjs --runs 3 --browser webkit --profile lte --scenario cold --source-root perf/.tmp/phase6-<variant> --out perf/results/phase6-<variant>.json
|
|
```
|
|
|
|
| Source | Commit | LTE FCP median ms | Wire bytes | app.js positive responses/sample |
|
|
|---|---|---:|---:|---:|
|
|
| Phase 2 | 4950d3e | 1044 | 1191063 | 2 |
|
|
| Immediately before lazy layouts | d98d444 | 1032 | 1191686 | 2 |
|
|
| First lazy-layout cut | 5d6a154 | 1615 | 1106796 | 2 |
|
|
| Phase 3 tip | cd4a25a | 1646 | 1108191 | 2 |
|
|
| Phase 5 tip (same product as Phase 4) | 21c1273 | 1736 | 1097007 | 2 |
|
|
| Phase 5 + worker force-cache | scratch | 1745 | 1097006 | 2 |
|
|
| Phase 5 + parser-owned classic CSS | scratch | 898 | 1097051 | 2 |
|
|
| Phase 5 + classic preload | scratch | 909 | 1097032 | 2 |
|
|
|
|
The adjacent-commit measurements isolate `5d6a154`, not the Phase 4 extraction.
|
|
All three FCP samples, complete proxy waterfalls, and page Resource Timing are
|
|
stored in each result. The first sample often includes startup compression cost;
|
|
it is retained in every median, not discarded.
|
|
|
|
Phase 3 sample 2: common styles finish around 880 ms. The parser-written classic
|
|
stylesheet is discovered at 416 ms but reaches the proxy only at 1434 ms and
|
|
finishes at 1607 ms. FCP is 1646 ms. Phase 5 sample 2: classic reaches the proxy
|
|
at 1540 ms, finishes at 1711 ms, FCP is 1736 ms. Speculatively discovered body
|
|
scripts already occupy the request queue when the selected stylesheet arrives.
|
|
Phase 2 discovers its declarative styles together around 231 ms, FCP 1044 ms.
|
|
|
|
The first service-worker request is at 2458 ms in Phase 3 and 2337 ms in Phase 5,
|
|
AFTER paint. Worker install competition does not explain this FCP regression.
|
|
Font preload URLs match the font CSS; late layout CSS is the final rendering
|
|
barrier. Making classic CSS declarative again removes the delay without changing
|
|
CSS bytes or cascade order. This scratch variant unconditionally applies classic
|
|
and is diagnostic only; the shipping fix must retain selected-layout behavior.
|
|
|
|
The modern synchronizer already uses default fetch caching. Changing it to
|
|
force-cache has no effect: every WebKit sample still transfers app.js twice.
|
|
The page and worker cannot reuse these HTTP-cache responses in this harness.
|
|
The next hypothesis was a same-build page handoff reusing the page HTTP cache.
|
|
The prototype checked both the X-Asset-Hash header and decoded-body SHA-256, and
|
|
stripped compressed transport headers before constructing the cached Response.
|
|
Updates and legacy migration must continue through their existing worker path.
|
|
|
|
The shipping CSS fix is a preload, not an unconditional stylesheet. Its three-run
|
|
FCP is 909 ms; the first classic request reaches the proxy at 250 ms and completes
|
|
at 423 ms. Lazy still applies only the saved layout, in the original cascade order.
|
|
Other selected layouts may speculatively download the small classic stylesheet;
|
|
it never applies or blocks their rendering. No inline script or CSP change.
|
|
|
|
|
|
The page-to-worker prototype successfully delivered bodies, but still transferred
|
|
app.js twice. `phase6-handoff-mode.json` records the two requests: identical URL,
|
|
`Accept-Encoding: gzip, deflate`, no-cors mode and immutable response, but script
|
|
versus empty request destinations. Force-cache in the page did not reuse the
|
|
script body's cache either. This prototype was discarded, not shipped.
|
|
|
|
A fetch preload plus a later fetch also failed the one-body assertion. The
|
|
shipping fix instead starts one cache-first fetch promise in the head loader.
|
|
The final eager app-bootstrap consumes that response, verifies header AND SHA-256,
|
|
and caches it before executing unchanged app.js as a classic script. A specific
|
|
server-generated CSP hash authorizes only those exact bytes; unsafe-inline remains
|
|
absent. DOMContentLoaded boot runs exactly once; the temporary script node and
|
|
response promise are released. Native, insecure HTTP and rollback modes retain
|
|
external classic execution. Only server asset-manifest rendering changed; no
|
|
frontend imports, worker sync algorithm, update flow or playback source changed.
|
|
|
|
The initial owned-response trial passed with one app.js body, FCP 1040 ms and
|
|
981468 wire bytes (one fresh sample; not a final median). Five-run acceptance and
|
|
regression results will be recorded separately. Historical diagnostics retained
|
|
all samples. Full-harness configurations now reset to the base tree before each
|
|
browser/profile, preventing a preceding synthetic update from contaminating the
|
|
next cold build. The historical invalid media fixture remains unchanged: home
|
|
launch only, not autoplay/audio latency.
|
|
|
|
|
|
Self-review added explicit N-1 app boot after eviction: verify the retained body
|
|
and use its exact classic URL through the controlling worker. It never fills the
|
|
new key with old bytes. Stale core execution additionally requires every group
|
|
contract to match the running shell's expectations; a core or feature contract
|
|
change rejects it. Both-engine lazy smoke now changes app bytes, evicts the new
|
|
entry, boots N-1 offline, then repairs the current entry before the existing
|
|
feature pinning/contract/playback checks. No source in app.js changed.
|
|
|
|
|
|
The all-engine inline prototype's completed five-run Chromium/LTE profile had
|
|
cold boot 6748 ms, warm boot 458 ms (Phase 5: 410 ms), offline boot 204 ms, core
|
|
update 870 ms. This was a real warm regression, so the full sweep was interrupted
|
|
before accepting its results. Raw output: perf/.tmp/phase6-inline-chromium-profile.log.
|
|
The native-script controlled variant measured warm 414 ms over five samples.
|
|
Shipping capture is therefore restricted to WebKit (including iOS CriOS); other
|
|
engines preload and retain their native classic-script/code-cache path. Normal
|
|
native cache hits avoid decoding/rehashing; retained core fallback still enforces
|
|
all group contracts. The new worker marks stale responses no-store and strips
|
|
decoded transport headers, preventing browser resource-cache poisoning under a
|
|
new URL. CacheStorage's exact keys and previous entries stay unchanged.
|
|
|
|
The native-window contract lookup trial regressed Chromium warm boot (~698 ms).
|
|
It is rejected. The worker now owns the all-group stale app contract guard
|
|
(pure planner and actual worker VM tests first); native boot has no window-side
|
|
CacheStorage or hashing work. WebKit's byte-verified owned response path is
|
|
unchanged. The native fixture models the actual worker fallback decision instead
|
|
of a second page-side decision. All 221 frontend tests and 184 server tests pass;
|
|
both-engine lazy/offline/eviction/pinning/contracts/playback smoke passes.
|
|
|
|
The WebKit warm prototype also paid repeated handoff/cache/hash work (warm
|
|
~98 ms versus Phase 5 83 ms). Capture now applies only to uncontrolled WebKit
|
|
visits. Controlled warm/offline/update pages use the worker's native exact-URL
|
|
script path, including its strengthened contract guard. A failing head-loader
|
|
test precedes this change; all 222 frontend and 184 server tests and both-engine
|
|
lazy smoke pass. Cold capture and both rollback flags are unchanged.
|
|
|
|
The final native-path review caught a new Chromium paint regression: five-run
|
|
FCP 1616/2328 ms (LTE/lossy), despite faster boot. A contemporary Phase 5 LTE
|
|
control measured 1360 ms over three runs. Lowering the new app preload priority
|
|
reduced FCP to 1396 ms (three runs). Native parser execution restores app's
|
|
original DOMContentLoaded boot boundary. A rejected no-preload controlled-page
|
|
trial worsened WebKit warm boot to 98 ms; native cache preloading remains.
|
|
|
|
The standalone helper adds a CacheStorage script read to native startup. Packing
|
|
the loader into the existing final core script, section-rail.js, measured Chrome
|
|
warm 425 ms versus contemporary Phase 5 426 ms (five runs); WebKit measured
|
|
95 ms versus 88 ms, so zero warm overhead is not yet established. The merged
|
|
three-run Chrome LTE cold trial measured FCP 1384 ms and boot 6512 ms. Core's
|
|
contract becomes 2 because an old section script lacks this loader and cannot
|
|
safely substitute for it. No Phase 5 SHELL file is removed; the experimental
|
|
Phase 6 standalone helper is removed. Native-order, exact final-script packing
|
|
and contract tests precede implementation. All 223 frontend and 184 server tests
|
|
and both-engine lazy/offline/eviction/pinning/contracts/playback smoke pass.
|
|
|
|
The intermediate native-auto-priority full dataset is retained as a rejected
|
|
trial; it is not the final acceptance result. Source directories named in trial
|
|
JSONs are dirty diagnostic worktrees of 9408ee0 with exactly the changes above.
|