Document incremental sync verification and performance gaps
This commit is contained in:
@@ -181,3 +181,34 @@ which receive hashed URLs as HTML scripts. Font preloads retain plain URLs to ma
|
|||||||
`fonts.css`; the webmanifest and its icon URLs also stay plain and precached.
|
`fonts.css`; the webmanifest and its icon URLs also stay plain and precached.
|
||||||
`piano-engine.mjs` is manifested but is historically absent from SHELL; this
|
`piano-engine.mjs` is manifested but is historically absent from SHELL; this
|
||||||
existing offline piano limitation is deferred to the loader phase.
|
existing offline piano limitation is deferred to the loader phase.
|
||||||
|
|
||||||
|
## Phase 2 incremental-sync verification
|
||||||
|
|
||||||
|
The current migration harness verifies the production page's own ready fast path
|
||||||
|
into `ytplayer-assets`: no `__ytpfresh` downloads, no reload before Refresh UI,
|
||||||
|
one banner/reload, an open N-1 tab, playback guard, incremental refresh after
|
||||||
|
an eviction, and offline launch. It preserves the legacy user-triggered reload
|
||||||
|
exception. Async CacheStorage/registration conditions are polled with awaited
|
||||||
|
`page.evaluate`; Playwright's `waitForFunction` does not poll async predicates.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
node perf/migration.mjs --browser all --profile lossy
|
||||||
|
node perf/migration.mjs --browser all --profile unthrottled
|
||||||
|
node perf/baseline.mjs --runs 1 --browser all --profile lte --scenario all \
|
||||||
|
--out perf/results/phase2-final-2026-10-07.json \
|
||||||
|
--compare perf/results/after-phase0-2026-10-07.json
|
||||||
|
ASSET_SYNC=0 node perf/baseline.mjs --runs 1 --browser all --profile lte \
|
||||||
|
--scenario offline --out perf/results/phase2-rollback-2026-10-07.json
|
||||||
|
ASSET_HASHING=0 node perf/baseline.mjs --runs 1 --browser all --profile lte \
|
||||||
|
--scenario offline --out perf/results/phase2-hashing-rollback-2026-10-07.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Results now include response paths/statuses and compressed response-body bytes
|
||||||
|
for cold/update runs. The total includes service-worker script checks/imports;
|
||||||
|
inspect individual responses to distinguish those from app asset downloads.
|
||||||
|
Migration results are `phase2-migration-<profile>-2026-10-07.json`.
|
||||||
|
`ASSET_SYNC=0` selects the legacy path while preserving the persistent utility
|
||||||
|
cache. `ASSET_HASHING=0` also selects legacy sync because single-tag URLs cannot
|
||||||
|
pass per-file hash checks. Current assets.json groups all block; idle loading and
|
||||||
|
lazy parsing await Phase 3. Incremental mode now caches the manifested
|
||||||
|
`piano-engine.mjs` even though it remains absent from the legacy SHELL.
|
||||||
|
|||||||
2082
perf/results/phase2-final-2026-10-07.json
Normal file
2082
perf/results/phase2-final-2026-10-07.json
Normal file
File diff suppressed because it is too large
Load Diff
131
perf/results/phase2-hashing-rollback-2026-10-07.json
Normal file
131
perf/results/phase2-hashing-rollback-2026-10-07.json
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
{
|
||||||
|
"date": "2026-10-07T16:00:49.668Z",
|
||||||
|
"commit": "bb446c717f92ef912f5000ddc757b9d1071120dc",
|
||||||
|
"runsConfigured": 1,
|
||||||
|
"browsers": {
|
||||||
|
"chromium": {
|
||||||
|
"lte": {
|
||||||
|
"offline": {
|
||||||
|
"requestCount": {
|
||||||
|
"median": 0,
|
||||||
|
"min": 0,
|
||||||
|
"max": 0,
|
||||||
|
"values": [
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"wireBytes": {
|
||||||
|
"median": 0,
|
||||||
|
"min": 0,
|
||||||
|
"max": 0,
|
||||||
|
"values": [
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"fcp": {
|
||||||
|
"median": 76,
|
||||||
|
"min": 76,
|
||||||
|
"max": 76,
|
||||||
|
"values": [
|
||||||
|
76
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"lcp": {
|
||||||
|
"median": 300,
|
||||||
|
"min": 300,
|
||||||
|
"max": 300,
|
||||||
|
"values": [
|
||||||
|
300
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"domContentLoaded": {
|
||||||
|
"median": 233,
|
||||||
|
"min": 233,
|
||||||
|
"max": 233,
|
||||||
|
"values": [
|
||||||
|
233
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"bootDone": {
|
||||||
|
"median": 279,
|
||||||
|
"min": 279,
|
||||||
|
"max": 279,
|
||||||
|
"values": [
|
||||||
|
279
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"reloadDuration": {
|
||||||
|
"median": 306,
|
||||||
|
"min": 306,
|
||||||
|
"max": 306,
|
||||||
|
"values": [
|
||||||
|
306
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"webkit": {
|
||||||
|
"lte": {
|
||||||
|
"offline": {
|
||||||
|
"requestCount": {
|
||||||
|
"median": 0,
|
||||||
|
"min": 0,
|
||||||
|
"max": 0,
|
||||||
|
"values": [
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"wireBytes": {
|
||||||
|
"median": 0,
|
||||||
|
"min": 0,
|
||||||
|
"max": 0,
|
||||||
|
"values": [
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"fcp": {
|
||||||
|
"median": 129,
|
||||||
|
"min": 129,
|
||||||
|
"max": 129,
|
||||||
|
"values": [
|
||||||
|
129
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"lcp": {
|
||||||
|
"median": 158,
|
||||||
|
"min": 158,
|
||||||
|
"max": 158,
|
||||||
|
"values": [
|
||||||
|
158
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"domContentLoaded": {
|
||||||
|
"median": 117,
|
||||||
|
"min": 117,
|
||||||
|
"max": 117,
|
||||||
|
"values": [
|
||||||
|
117
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"bootDone": {
|
||||||
|
"median": 153,
|
||||||
|
"min": 153,
|
||||||
|
"max": 153,
|
||||||
|
"values": [
|
||||||
|
153
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"reloadDuration": {
|
||||||
|
"median": 165,
|
||||||
|
"min": 165,
|
||||||
|
"max": 165,
|
||||||
|
"values": [
|
||||||
|
165
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
41
perf/results/phase2-migration-lossy-2026-10-07.json
Normal file
41
perf/results/phase2-migration-lossy-2026-10-07.json
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"commit": "b77938a",
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"browser": "chromium",
|
||||||
|
"oldTag": "1175f1a1d2c1",
|
||||||
|
"newTag": "4f7090fff60c",
|
||||||
|
"banners": 1,
|
||||||
|
"updateReloads": 1,
|
||||||
|
"cachedFiles": 92,
|
||||||
|
"durationMs": 27514,
|
||||||
|
"wireBytes": 622009,
|
||||||
|
"offline": true,
|
||||||
|
"legacyURLs": 21,
|
||||||
|
"profile": "lossy",
|
||||||
|
"userInitiatedOnly": true,
|
||||||
|
"playbackGuard": true,
|
||||||
|
"evictionRepair": true,
|
||||||
|
"incrementalRefresh": true,
|
||||||
|
"offlineTransportErrors": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"browser": "webkit",
|
||||||
|
"oldTag": "1175f1a1d2c1",
|
||||||
|
"newTag": "4f7090fff60c",
|
||||||
|
"banners": 1,
|
||||||
|
"updateReloads": 1,
|
||||||
|
"cachedFiles": 92,
|
||||||
|
"durationMs": 19558,
|
||||||
|
"wireBytes": 731221,
|
||||||
|
"offline": true,
|
||||||
|
"legacyURLs": 21,
|
||||||
|
"profile": "lossy",
|
||||||
|
"userInitiatedOnly": true,
|
||||||
|
"playbackGuard": true,
|
||||||
|
"evictionRepair": true,
|
||||||
|
"incrementalRefresh": true,
|
||||||
|
"offlineTransportErrors": 4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
41
perf/results/phase2-migration-unthrottled-2026-10-07.json
Normal file
41
perf/results/phase2-migration-unthrottled-2026-10-07.json
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"commit": "b77938a",
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"browser": "chromium",
|
||||||
|
"oldTag": "1175f1a1d2c1",
|
||||||
|
"newTag": "4f7090fff60c",
|
||||||
|
"banners": 1,
|
||||||
|
"updateReloads": 1,
|
||||||
|
"cachedFiles": 92,
|
||||||
|
"durationMs": 10811,
|
||||||
|
"wireBytes": 630657,
|
||||||
|
"offline": true,
|
||||||
|
"legacyURLs": 21,
|
||||||
|
"profile": "unthrottled",
|
||||||
|
"userInitiatedOnly": true,
|
||||||
|
"playbackGuard": true,
|
||||||
|
"evictionRepair": true,
|
||||||
|
"incrementalRefresh": true,
|
||||||
|
"offlineTransportErrors": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"browser": "webkit",
|
||||||
|
"oldTag": "1175f1a1d2c1",
|
||||||
|
"newTag": "4f7090fff60c",
|
||||||
|
"banners": 1,
|
||||||
|
"updateReloads": 1,
|
||||||
|
"cachedFiles": 92,
|
||||||
|
"durationMs": 9283,
|
||||||
|
"wireBytes": 744401,
|
||||||
|
"offline": true,
|
||||||
|
"legacyURLs": 21,
|
||||||
|
"profile": "unthrottled",
|
||||||
|
"userInitiatedOnly": true,
|
||||||
|
"playbackGuard": true,
|
||||||
|
"evictionRepair": true,
|
||||||
|
"incrementalRefresh": true,
|
||||||
|
"offlineTransportErrors": 4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
131
perf/results/phase2-rollback-2026-10-07.json
Normal file
131
perf/results/phase2-rollback-2026-10-07.json
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
{
|
||||||
|
"date": "2026-10-07T15:55:07.011Z",
|
||||||
|
"commit": "54a07a0a2ae1711e441545b208c45c55b3318963",
|
||||||
|
"runsConfigured": 1,
|
||||||
|
"browsers": {
|
||||||
|
"chromium": {
|
||||||
|
"lte": {
|
||||||
|
"offline": {
|
||||||
|
"requestCount": {
|
||||||
|
"median": 0,
|
||||||
|
"min": 0,
|
||||||
|
"max": 0,
|
||||||
|
"values": [
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"wireBytes": {
|
||||||
|
"median": 0,
|
||||||
|
"min": 0,
|
||||||
|
"max": 0,
|
||||||
|
"values": [
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"fcp": {
|
||||||
|
"median": 72,
|
||||||
|
"min": 72,
|
||||||
|
"max": 72,
|
||||||
|
"values": [
|
||||||
|
72
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"lcp": {
|
||||||
|
"median": 72,
|
||||||
|
"min": 72,
|
||||||
|
"max": 72,
|
||||||
|
"values": [
|
||||||
|
72
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"domContentLoaded": {
|
||||||
|
"median": 225,
|
||||||
|
"min": 225,
|
||||||
|
"max": 225,
|
||||||
|
"values": [
|
||||||
|
225
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"bootDone": {
|
||||||
|
"median": 249,
|
||||||
|
"min": 249,
|
||||||
|
"max": 249,
|
||||||
|
"values": [
|
||||||
|
249
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"reloadDuration": {
|
||||||
|
"median": 262,
|
||||||
|
"min": 262,
|
||||||
|
"max": 262,
|
||||||
|
"values": [
|
||||||
|
262
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"webkit": {
|
||||||
|
"lte": {
|
||||||
|
"offline": {
|
||||||
|
"requestCount": {
|
||||||
|
"median": 0,
|
||||||
|
"min": 0,
|
||||||
|
"max": 0,
|
||||||
|
"values": [
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"wireBytes": {
|
||||||
|
"median": 0,
|
||||||
|
"min": 0,
|
||||||
|
"max": 0,
|
||||||
|
"values": [
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"fcp": {
|
||||||
|
"median": 109,
|
||||||
|
"min": 109,
|
||||||
|
"max": 109,
|
||||||
|
"values": [
|
||||||
|
109
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"lcp": {
|
||||||
|
"median": 138,
|
||||||
|
"min": 138,
|
||||||
|
"max": 138,
|
||||||
|
"values": [
|
||||||
|
138
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"domContentLoaded": {
|
||||||
|
"median": 101,
|
||||||
|
"min": 101,
|
||||||
|
"max": 101,
|
||||||
|
"values": [
|
||||||
|
101
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"bootDone": {
|
||||||
|
"median": 133,
|
||||||
|
"min": 133,
|
||||||
|
"max": 133,
|
||||||
|
"values": [
|
||||||
|
133
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"reloadDuration": {
|
||||||
|
"median": 145,
|
||||||
|
"min": 145,
|
||||||
|
"max": 145,
|
||||||
|
"values": [
|
||||||
|
145
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
43
plans/phase2-report.md
Normal file
43
plans/phase2-report.md
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# Phase 2 report
|
||||||
|
|
||||||
|
Shipped on `codex/phase2`: plan `a1f16f2`; incremental sync/playback guards
|
||||||
|
`54a07a0`; atomic state, exact hash rejection and retention `5b25cca`;
|
||||||
|
single-tag rollback compatibility `bb446c7`; migration verification `5d1e5ec`;
|
||||||
|
fail-closed status handling `9240456`.
|
||||||
|
|
||||||
|
Persistent `ytplayer-assets` stores verified exact URLs and current/previous
|
||||||
|
manifests. Downloads resume, use six workers/three attempts, and publish only
|
||||||
|
complete blocking sets. Activation retains N-1 changed/removed files, prunes
|
||||||
|
N-2, then deletes legacy caches; quota is logged. All current groups block;
|
||||||
|
lazy parsing/background warming await Phase 3.
|
||||||
|
|
||||||
|
Server gaps addressed: inject ASSET_SYNC and the hashed sync-core import,
|
||||||
|
hash final worker bytes, compress manifest responses while preserving build
|
||||||
|
ETags. ASSET_SYNC=0 selects legacy sync; ASSET_HASHING=0 also selects legacy.
|
||||||
|
|
||||||
|
Verification: 168 frontend/181 server tests pass without skips. Chromium/WebKit
|
||||||
|
migration passes with and without stalls using actual b77938a code: ready:true,
|
||||||
|
zero legacy refresh downloads, one banner/user-triggered reload, N-1 open tab,
|
||||||
|
eviction repair, incremental refresh and offline boot. Both rollback flags
|
||||||
|
pass offline browser checks. Async polling fixes the Playwright harness race.
|
||||||
|
|
||||||
|
Accepted legacy exception: b77938a retains its four-second timer after the USER
|
||||||
|
presses Refresh UI and does not report playback. New pages guard playback,
|
||||||
|
offer explicit override and post PLAYING; workers defer known-playing requests
|
||||||
|
and never call skipWaiting during installation.
|
||||||
|
|
||||||
|
Final one-run LTE measurements (`phase2-final-2026-10-07.json`, Chromium/WebKit):
|
||||||
|
JS updates 155,648/189,354 bytes versus 611,338/680,822; CSS 31,476/30,545 versus
|
||||||
|
611,476/680,831. Sync fetches changed app/style + index/manifest; fonts/icons transfer
|
||||||
|
zero bytes. Browser worker checks add overhead: Chromium downloads sw.js twice;
|
||||||
|
WebKit also downloads the unchanged imported core. Thus total CSS exceeds
|
||||||
|
30,000 bytes.
|
||||||
|
|
||||||
|
Cold bytes: 624,762/1,191,130 versus 1,040,158/1,180,749. Chromium transfers app.js
|
||||||
|
once; WebKit transfers it twice despite HTTP-cache reuse attempts. Cache sharing
|
||||||
|
remains unresolved. Cold boot: 11,155/4,327 ms versus 10,480/3,290; warm:
|
||||||
|
671/121 versus 692/139; offline: 264/133 versus 259/137. Single-run cold regressions
|
||||||
|
need further investigation; no claim that every performance target was met.
|
||||||
|
|
||||||
|
Owner iPhone checks: locked playback, override/cancel, stall recovery, offline
|
||||||
|
launch and OPFS/quota coexistence. No push, merge or deployment.
|
||||||
Reference in New Issue
Block a user