Verify six app seams and record Phase 4 performance measurements
This commit is contained in:
@@ -271,3 +271,43 @@ Legacy pages cannot report their selected layout. Their one-time migration block
|
||||
all layouts to preserve immediate offline selection; modern pages block only the
|
||||
reported layout and its shared controls. Executing groups never re-evaluate live.
|
||||
See plans/phase3-staged-apply-decision.md: Phase 4 must add disposal/state handoff.
|
||||
|
||||
## Phase 4 seams and verification
|
||||
|
||||
The dependency inventory in `plans/phase4-seams.md` records Phase 3 declarations,
|
||||
resolved outside references and byte/coupling rankings. Reproduce its source using
|
||||
`npm install --prefix perf/.tmp/analysis --no-audit --no-fund acorn@8 eslint-scope@8`
|
||||
and `node perf/analyze-app.cjs cd4a25a` (development scratch dependencies only).
|
||||
Shell/shared view/Settings/section-rail definitions remain eager before app.js.
|
||||
Presenter, Remote client, Watch party, Share/External and Stats view register
|
||||
classic singletons on `window.YT`; synchronous playback hooks remain facades.
|
||||
Executing chunks remain pinned: disposal/state handoff is still required before
|
||||
any live replacement can be enabled.
|
||||
|
||||
```bash
|
||||
node --test frontend/*.test.js
|
||||
(cd server && bun install && bun run test)
|
||||
node perf/hidden-timers.mjs
|
||||
node perf/seams.mjs --browser all
|
||||
node perf/lazy.mjs --browser all
|
||||
node perf/migration.mjs --browser all --profile lossy \
|
||||
--out perf/results/phase4-migration-lossy-2026-10-08.json
|
||||
node perf/migration.mjs --browser all --profile unthrottled \
|
||||
--out perf/results/phase4-migration-unthrottled-2026-10-08.json
|
||||
node perf/baseline.mjs --runs 1 --browser all --profile lte --scenario all \
|
||||
--out perf/results/phase4-final-2026-10-08.json \
|
||||
--compare perf/results/after-phase0-2026-10-07.json
|
||||
node perf/baseline.mjs --runs 3 --browser chromium --profile lte --scenario cold \
|
||||
--out perf/results/phase4-cold-isolated-2026-10-08.json
|
||||
```
|
||||
|
||||
`update-feature` appends one comment to presenter.js in scratch, installs the worker,
|
||||
explicitly activates, then waits for the changed background chunk to be verified
|
||||
in CacheStorage. It asserts that no other application JS/CSS/font/icon payload
|
||||
transfers; derived index/manifest and worker script checks are included in totals.
|
||||
`all` includes this scenario when the source contains presenter.js. Cold records
|
||||
now include individual long-task timing without changing the aggregate metric,
|
||||
plus the source frontend build tag. WebKit does not expose the long-task API.
|
||||
Migration supports `--out` to preserve earlier phase evidence. Existing lazy
|
||||
harness results are copied to `phase4-lazy-2026-10-08.json` after each Phase 4 run
|
||||
and the Phase 3 result is restored. No production requests or deploys are needed.
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
const fs=require('fs'), acorn=require('./.tmp/analysis/node_modules/acorn'), scope=require('./.tmp/analysis/node_modules/eslint-scope');
|
||||
const src=fs.readFileSync('frontend/app.js','utf8');
|
||||
const {execFileSync}=require('node:child_process');
|
||||
const commit=process.argv[2];
|
||||
const read=file=>commit?execFileSync('git',['show',commit+':'+file],{encoding:'utf8',maxBuffer:2000000}):fs.readFileSync(file,'utf8');
|
||||
const src=read('frontend/app.js');
|
||||
function parse(s){return acorn.parse(s,{ecmaVersion:2024,sourceType:'script',locations:true,ranges:true});}
|
||||
const ast=parse(src), mgr=scope.analyze(ast,{ecmaVersion:2024,sourceType:'script',optimistic:true,ignoreEval:true});
|
||||
const vars=mgr.globalScope.variables, names=new Set(vars.map(v=>v.name));
|
||||
const rows=vars.map(v=>{const decl=v.defs[0].parent||v.defs[0].node;const stmt=ast.body.find(n=>n.start<=decl.start&&n.end>=decl.end);return {name:v.name,start:stmt.start,end:stmt.end,line:stmt.loc.start.line,bytes:Buffer.byteLength(src.slice(stmt.start,stmt.end)),outside:v.references.filter(r=>r.identifier.start<stmt.start||r.identifier.start>=stmt.end).map(r=>r.identifier.loc.start.line),imports:[]};});
|
||||
for(const row of rows){const deps=new Set();for(const v of vars)if(v.name!==row.name&&v.references.some(r=>r.identifier.start>=row.start&&r.identifier.start<row.end))deps.add(v.name);row.imports=[...deps];}
|
||||
for(const file of fs.readdirSync('frontend').filter(f=>f.endsWith('.js')&&!f.endsWith('.test.js')&&f!=='app.js')){try{const other=scope.analyze(parse(fs.readFileSync('frontend/'+file,'utf8')),{ecmaVersion:2024,sourceType:'script',optimistic:true,ignoreEval:true});for(const r of other.globalScope.through){if(names.has(r.identifier.name))rows.find(x=>x.name===r.identifier.name).outside.push(file+':'+r.identifier.loc.start.line);}}catch(e){if(!file.includes('entry'))console.error(file,e.message);}}
|
||||
for(const file of (commit?execFileSync('git',['ls-tree','--name-only',commit+':frontend'],{encoding:'utf8'}).trim().split('\n'):fs.readdirSync('frontend')).filter(f=>f.endsWith('.js')&&!f.endsWith('.test.js')&&f!=='app.js')){try{const other=scope.analyze(parse(read('frontend/'+file)),{ecmaVersion:2024,sourceType:'script',optimistic:true,ignoreEval:true});for(const r of other.globalScope.through){if(names.has(r.identifier.name))rows.find(x=>x.name===r.identifier.name).outside.push(file+':'+r.identifier.loc.start.line);}}catch(e){if(!file.includes('entry'))console.error(file,e.message);}}
|
||||
fs.writeFileSync('perf/.tmp/analysis/declarations.json',JSON.stringify(rows,null,2));
|
||||
const candidates={shell:['Recommendations','renderSidebar','renderHomePlaylists','updateHomeGridScrollState','updateBottomChrome','setHomeOverPlayer','showMiniBar','updateMiniBar','hideMiniBar','setTile','updateNowPlayingActions','renderSmartSidebar'],presenter:['Presenter'],remote:['Remote'],party:['Party'],share:['Share','External'],stats:['renderStats'],notes:['Notes'],settings:['renderSettings'],service:['ServiceVisual','enterServiceMode','exitServiceMode'],editor:['openVideoEditor'],export:['exportToDevice'],sectionRail:['SectionRail'],gestures:['Gestures']};
|
||||
const summary=Object.entries(candidates).map(([name,list])=>{const chosen=rows.filter(r=>list.includes(r.name));const coupling=new Set(chosen.flatMap(r=>r.imports).filter(n=>!list.includes(n)));return {name,bytes:chosen.reduce((s,r)=>s+r.bytes,0),coupling:coupling.size,ratio:Math.round(chosen.reduce((s,r)=>s+r.bytes,0)/Math.max(1,coupling.size)),imports:[...coupling],outside:chosen.flatMap(r=>r.outside),list};}).sort((a,b)=>b.ratio-a.ratio);fs.writeFileSync('perf/.tmp/analysis/candidates.json',JSON.stringify(summary,null,2));console.log(summary.map(r=>[r.name,r.bytes,r.coupling,r.ratio].join(' ')).join('\n'));
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
* --compare <json-path> Compare results against a previous baseline JSON
|
||||
*/
|
||||
|
||||
import assert from 'node:assert/strict';
|
||||
import { createHash } from 'node:crypto';
|
||||
import { spawn, spawnSync, execFileSync } from 'node:child_process';
|
||||
import { existsSync, mkdirSync, rmSync, cpSync, appendFileSync, statSync, writeFileSync, readFileSync, symlinkSync, unlinkSync } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
@@ -244,6 +246,7 @@ async function setupPageMetrics(page) {
|
||||
window.__fcp = null;
|
||||
window.__lcp = null;
|
||||
window.__longTasksTotal = 0;
|
||||
window.__longTasks = [];
|
||||
|
||||
// Observe boot completion landmark (#cards view set by renderList())
|
||||
const markBoot = () => {
|
||||
@@ -263,6 +266,7 @@ async function setupPageMetrics(page) {
|
||||
new PerformanceObserver((list) => {
|
||||
for (const entry of list.getEntries()) {
|
||||
window.__longTasksTotal += entry.duration;
|
||||
window.__longTasks.push({start:Math.round(entry.startTime),duration:Math.round(entry.duration)});
|
||||
}
|
||||
}).observe({ type: 'longtask', buffered: true });
|
||||
} catch {}
|
||||
@@ -374,6 +378,7 @@ async function runColdScenario({ browserType, server, proxy, profile }) {
|
||||
domContentLoaded: nav ? Math.round(nav.domContentLoadedEventEnd - nav.startTime) : null,
|
||||
bootDone: window.__bootDone ? Math.round(window.__bootDone) : null,
|
||||
longTaskTotal: Math.round(window.__longTasksTotal || 0),
|
||||
longTasks: window.__longTasks || [],
|
||||
};
|
||||
});
|
||||
|
||||
@@ -396,6 +401,7 @@ async function runColdScenario({ browserType, server, proxy, profile }) {
|
||||
domContentLoaded: pageMetrics.domContentLoaded,
|
||||
bootDone: pageMetrics.bootDone,
|
||||
longTaskTotal: pageMetrics.longTaskTotal,
|
||||
longTasks: pageMetrics.longTasks,
|
||||
requests: stats.requests,
|
||||
initialJsCss: pageMetrics.initialJsCss,
|
||||
initialAssetRequests: pageMetrics.initialAssetRequests,
|
||||
@@ -478,6 +484,7 @@ async function runWarmScenario({ browserType, server, proxy, profile }) {
|
||||
domContentLoaded: nav ? Math.round(nav.domContentLoadedEventEnd - nav.startTime) : null,
|
||||
bootDone: window.__bootDone ? Math.round(window.__bootDone) : null,
|
||||
longTaskTotal: Math.round(window.__longTasksTotal || 0),
|
||||
longTasks: window.__longTasks || [],
|
||||
};
|
||||
});
|
||||
|
||||
@@ -492,6 +499,7 @@ async function runWarmScenario({ browserType, server, proxy, profile }) {
|
||||
domContentLoaded: pageMetrics.domContentLoaded,
|
||||
bootDone: pageMetrics.bootDone,
|
||||
longTaskTotal: pageMetrics.longTaskTotal,
|
||||
longTasks: pageMetrics.longTasks,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -634,7 +642,7 @@ async function runUpdateScenario({ browserType, server, proxy, profile, updateKi
|
||||
}
|
||||
|
||||
// Switch server to Tree N+1 (app.js or theme-glass.css modification)
|
||||
const targetTree = updateKind === 'js' ? trees.treeUpdateJs : trees.treeUpdateCss;
|
||||
const targetTree = updateKind === 'feature' ? trees.treeUpdateFeature : updateKind === 'js' ? trees.treeUpdateJs : trees.treeUpdateCss;
|
||||
await server.restartWithPublic(targetTree);
|
||||
|
||||
// Measure wire bytes and duration from reg.update() until new SW is waiting/installed
|
||||
@@ -654,10 +662,32 @@ async function runUpdateScenario({ browserType, server, proxy, profile, updateKi
|
||||
await sleep(50);
|
||||
}
|
||||
|
||||
if (updateKind === 'feature') {
|
||||
// Readiness excludes background chunks. Include activation and the changed
|
||||
// feature's actual idle transfer rather than reporting readiness as its cost.
|
||||
const expected = createHash('sha256').update(readFileSync(path.join(targetTree,'presenter.js'))).digest('hex').slice(0,10);
|
||||
await page.evaluate(async()=>{const r=await navigator.serviceWorker.getRegistration();r.waiting.postMessage({type:'SKIP_WAITING'});});
|
||||
const end=Date.now()+90000;
|
||||
while(true) {
|
||||
const complete=await page.evaluate(async h=>{
|
||||
const r=await navigator.serviceWorker.getRegistration();
|
||||
if(r.waiting || r.installing)return false;
|
||||
r.active?.postMessage({type:'WARM_ASSETS',saveData:false});
|
||||
const c=await caches.open('ytplayer-assets'),entry=await c.match('/presenter.js?v='+h);
|
||||
return entry?.headers.get('X-Asset-Hash')===h;
|
||||
},expected);
|
||||
if(complete)break;
|
||||
if(Date.now()>end)throw Error('Changed feature was not cached after activation');
|
||||
await sleep(100);
|
||||
}
|
||||
}
|
||||
const duration = Date.now() - t0;
|
||||
proxy.stopTracking();
|
||||
const stats = proxy.getStats();
|
||||
|
||||
if(updateKind==='feature') {
|
||||
const assetDownloads=stats.requests.filter(r=>r.bytes>0).map(r=>new URL(r.url,navUrl).pathname).filter(p=>/\.(?:js|css|woff2?|png|svg)$/.test(p)&&!['/sw.js','/asset-sync-core.js'].includes(p));
|
||||
assert.deepEqual([...new Set(assetDownloads)],['/presenter.js'],'feature edit transfers only its chunk; no app/core/font/icon payload');
|
||||
}
|
||||
await browser.close();
|
||||
|
||||
return {
|
||||
@@ -696,6 +726,7 @@ async function main() {
|
||||
const treeBase = path.join(tmpRoot, 'tree-base');
|
||||
const treeUpdateJs = path.join(tmpRoot, 'tree-update-js');
|
||||
const treeUpdateCss = path.join(tmpRoot, 'tree-update-css');
|
||||
const treeUpdateFeature = path.join(tmpRoot, 'tree-update-feature');
|
||||
|
||||
let frontendSource=path.join(REPO_ROOT,'frontend');
|
||||
if(options.frontendCommit) {
|
||||
@@ -704,14 +735,15 @@ async function main() {
|
||||
execFileSync('tar',['-xf',archive,'-C',tmpRoot]);
|
||||
frontendSource=path.join(tmpRoot,'frontend');
|
||||
}
|
||||
for(const tree of [treeBase,treeUpdateJs,treeUpdateCss])cpSync(frontendSource,tree,{recursive:true});
|
||||
for(const tree of [treeBase,treeUpdateJs,treeUpdateCss,treeUpdateFeature])cpSync(frontendSource,tree,{recursive:true});
|
||||
|
||||
// Append 1 comment line to app.js in treeUpdateJs
|
||||
appendFileSync(path.join(treeUpdateJs, 'app.js'), '\n// baseline bench: 1-line app.js comment\n');
|
||||
// Append 1 rule to theme-glass.css in treeUpdateCss
|
||||
appendFileSync(path.join(treeUpdateCss, 'theme-glass.css'), '\n/* baseline bench: 1-line css rule */\n.baseline-marker { opacity: 0.99; }\n');
|
||||
|
||||
const trees = { treeBase, treeUpdateJs, treeUpdateCss };
|
||||
if(existsSync(path.join(treeUpdateFeature,'presenter.js')))appendFileSync(path.join(treeUpdateFeature,'presenter.js'),'\n// baseline bench: 1-line presenter chunk comment\n');
|
||||
const trees = { treeBase, treeUpdateJs, treeUpdateCss, treeUpdateFeature };
|
||||
|
||||
const serverScratch = path.join(tmpRoot, 'server-run');
|
||||
const server = new ServerManager(serverScratch, treeBase);
|
||||
@@ -721,6 +753,7 @@ async function main() {
|
||||
const results = {
|
||||
date: new Date().toISOString(),
|
||||
frontendCommit: options.frontendCommit,
|
||||
frontendBuildTag: (await (await fetch('http://127.0.0.1:'+server.port+'/api/version')).json()).buildTag,
|
||||
commit: spawnSync('git', ['rev-parse', 'HEAD'], { cwd: REPO_ROOT }).stdout.toString().trim(),
|
||||
runsConfigured: options.runs,
|
||||
browsers: {},
|
||||
@@ -759,6 +792,7 @@ async function main() {
|
||||
domContentLoaded: summarizeList(coldRuns.map((r) => r.domContentLoaded)),
|
||||
bootDone: summarizeList(coldRuns.map((r) => r.bootDone)),
|
||||
longTaskTotal: summarizeList(coldRuns.map((r) => r.longTaskTotal)),
|
||||
longTasks: coldRuns.map(r=>r.longTasks),
|
||||
swInstallDuration: summarizeList(coldRuns.map((r) => r.swInstallDuration)),
|
||||
swInstallBytes: summarizeList(coldRuns.map((r) => r.swInstallBytes)),
|
||||
storageEstimate: coldRuns[0]?.storageEstimate || null,
|
||||
@@ -869,6 +903,16 @@ async function main() {
|
||||
};
|
||||
}
|
||||
|
||||
if ((options.scenario === 'all' || options.scenario === 'update-feature') && existsSync(path.join(treeBase,'presenter.js'))) {
|
||||
console.log(` [Scenario: Update split-out presenter, including idle cache fill] running ${options.runs} iterations...`);
|
||||
const runs=[];
|
||||
for(let r=0;r<options.runs;r++) {
|
||||
const res=await runUpdateScenario({browserType:bType,server,proxy,profile:prof,updateKind:'feature',trees});runs.push(res);
|
||||
console.log(` run ${r+1}/${options.runs}: ${res.wireBytes} bytes, ${res.requestCount} reqs, dur=${res.duration}ms`);
|
||||
}
|
||||
results.browsers[bName][prof].updateFeature={requestCount:summarizeList(runs.map(r=>r.requestCount)),wireBytes:summarizeList(runs.map(r=>r.wireBytes)),duration:summarizeList(runs.map(r=>r.duration)),wireBytesByType:runs[0]?.wireBytesByType||{},requests:runs[0]?.requests||[]};
|
||||
}
|
||||
|
||||
await proxy.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,5 +234,5 @@ async function run(name) {
|
||||
try {
|
||||
const results = [];
|
||||
for (const name of browserName === 'all' ? ['chromium', 'webkit'] : [browserName]) results.push(await run(name));
|
||||
writeFileSync(join(repo, `perf/results/phase3-migration-${profile}-2026-10-08.json`), JSON.stringify({ commit, results }, null, 2) + '\n');
|
||||
writeFileSync(args.includes('--out') ? resolve(args[args.indexOf('--out')+1]) : join(repo, `perf/results/phase3-migration-${profile}-2026-10-08.json`), JSON.stringify({ commit, results }, null, 2) + '\n');
|
||||
} finally { rmSync(scratch, { recursive: true, force: true }); }
|
||||
|
||||
931
perf/results/phase4-cold-isolated-2026-10-08.json
Normal file
931
perf/results/phase4-cold-isolated-2026-10-08.json
Normal file
@@ -0,0 +1,931 @@
|
||||
{
|
||||
"date": "2026-10-07T20:55:14.741Z",
|
||||
"frontendCommit": null,
|
||||
"frontendBuildTag": "c3dbdd7039db",
|
||||
"commit": "2c5003575c641fddb128c6d1d14bb5d1e3999efb",
|
||||
"runsConfigured": 3,
|
||||
"browsers": {
|
||||
"chromium": {
|
||||
"lte": {
|
||||
"cold": {
|
||||
"requestCount": {
|
||||
"median": 115,
|
||||
"min": 115,
|
||||
"max": 115,
|
||||
"values": [
|
||||
115,
|
||||
115,
|
||||
115
|
||||
]
|
||||
},
|
||||
"wireBytes": {
|
||||
"median": 651012,
|
||||
"min": 651012,
|
||||
"max": 651012,
|
||||
"values": [
|
||||
651012,
|
||||
651012,
|
||||
651012
|
||||
]
|
||||
},
|
||||
"fcp": {
|
||||
"median": 1352,
|
||||
"min": 1352,
|
||||
"max": 1384,
|
||||
"values": [
|
||||
1384,
|
||||
1352,
|
||||
1352
|
||||
]
|
||||
},
|
||||
"lcp": {
|
||||
"median": 1352,
|
||||
"min": 1352,
|
||||
"max": 1384,
|
||||
"values": [
|
||||
1384,
|
||||
1352,
|
||||
1352
|
||||
]
|
||||
},
|
||||
"domContentLoaded": {
|
||||
"median": 6992,
|
||||
"min": 6973,
|
||||
"max": 7373,
|
||||
"values": [
|
||||
7373,
|
||||
6992,
|
||||
6973
|
||||
]
|
||||
},
|
||||
"bootDone": {
|
||||
"median": 7010,
|
||||
"min": 6989,
|
||||
"max": 7389,
|
||||
"values": [
|
||||
7389,
|
||||
7010,
|
||||
6989
|
||||
]
|
||||
},
|
||||
"longTaskTotal": {
|
||||
"median": 275,
|
||||
"min": 274,
|
||||
"max": 297,
|
||||
"values": [
|
||||
297,
|
||||
274,
|
||||
275
|
||||
]
|
||||
},
|
||||
"longTasks": [
|
||||
[
|
||||
{
|
||||
"start": 1232,
|
||||
"duration": 135
|
||||
},
|
||||
{
|
||||
"start": 7216,
|
||||
"duration": 162
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"start": 1223,
|
||||
"duration": 109
|
||||
},
|
||||
{
|
||||
"start": 6834,
|
||||
"duration": 165
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"start": 1225,
|
||||
"duration": 111
|
||||
},
|
||||
{
|
||||
"start": 6814,
|
||||
"duration": 164
|
||||
}
|
||||
]
|
||||
],
|
||||
"swInstallDuration": {
|
||||
"median": 36619,
|
||||
"min": 36567,
|
||||
"max": 36956,
|
||||
"values": [
|
||||
36956,
|
||||
36567,
|
||||
36619
|
||||
]
|
||||
},
|
||||
"swInstallBytes": {
|
||||
"median": 651012,
|
||||
"min": 651012,
|
||||
"max": 651012,
|
||||
"values": [
|
||||
651012,
|
||||
651012,
|
||||
651012
|
||||
]
|
||||
},
|
||||
"storageEstimate": {
|
||||
"usage": 2801669,
|
||||
"quota": 5371510789
|
||||
},
|
||||
"mediaReady": {
|
||||
"median": null,
|
||||
"min": null,
|
||||
"max": null,
|
||||
"values": [
|
||||
null,
|
||||
null,
|
||||
null
|
||||
]
|
||||
},
|
||||
"autoplayBlocked": true,
|
||||
"wireBytesByType": {
|
||||
"html": 22882,
|
||||
"js": 296653,
|
||||
"css": 65916,
|
||||
"fonts": 254048,
|
||||
"images": 6278,
|
||||
"media": 0,
|
||||
"api": 4604,
|
||||
"other": 631
|
||||
},
|
||||
"requests": [
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/?v=benchmedia01",
|
||||
"status": 200,
|
||||
"bytes": 11441
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/fonts/HankenGrotesk-latin.woff2",
|
||||
"status": 200,
|
||||
"bytes": 34704
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/fonts/BricolageGrotesque-latin.woff2",
|
||||
"status": 200,
|
||||
"bytes": 76888
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/lazy.js?v=99caff8ebd",
|
||||
"status": 200,
|
||||
"bytes": 2543
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/theme-classic.css?v=d420fcfb12",
|
||||
"status": 200,
|
||||
"bytes": 3529
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/fonts/fonts.css?v=dda3dfb804",
|
||||
"status": 200,
|
||||
"bytes": 391
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/styles.css?v=9f3a5dea41",
|
||||
"status": 200,
|
||||
"bytes": 27364
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/service-ui.css?v=b9bf96a3a8",
|
||||
"status": 200,
|
||||
"bytes": 3736
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/refresh.css?v=62498384f1",
|
||||
"status": 200,
|
||||
"bytes": 5027
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/layout-base.css?v=4f3307cd3b",
|
||||
"status": 200,
|
||||
"bytes": 278
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/recommendations.css?v=055101368d",
|
||||
"status": 200,
|
||||
"bytes": 790
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/settings-sections.css?v=055507ab85",
|
||||
"status": 200,
|
||||
"bytes": 873
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/offline-pages.css?v=2889456261",
|
||||
"status": 200,
|
||||
"bytes": 859
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/saved-page.css?v=3ff576a784",
|
||||
"status": 200,
|
||||
"bytes": 537
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/fullscreen-orientation.css?v=91f2d84453",
|
||||
"status": 200,
|
||||
"bytes": 1415
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/related-videos.css?v=5a616b1be8",
|
||||
"status": 200,
|
||||
"bytes": 404
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/download-actions.css?v=12d3bcfe3e",
|
||||
"status": 200,
|
||||
"bytes": 430
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/fingerprint.js?v=a635143269",
|
||||
"status": 200,
|
||||
"bytes": 1034
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/opfs.js?v=df7a8d0391",
|
||||
"status": 200,
|
||||
"bytes": 3920
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/lyrics-core.js?v=4dcdac2edd",
|
||||
"status": 200,
|
||||
"bytes": 2632
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/lyrics-display.js?v=48e8550175",
|
||||
"status": 200,
|
||||
"bytes": 571
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/flag-ui.js?v=eeae1c1d1a",
|
||||
"status": 200,
|
||||
"bytes": 2036
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/sha256-wasm.js?v=393c50ba56",
|
||||
"status": 200,
|
||||
"bytes": 1521
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/sha256.js?v=cd9b980e6f",
|
||||
"status": 200,
|
||||
"bytes": 2733
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/loudness-wasm.js?v=c6102d7844",
|
||||
"status": 200,
|
||||
"bytes": 1130
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/loudness.js?v=01b3da88dd",
|
||||
"status": 200,
|
||||
"bytes": 1818
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/device-db.js?v=880c5cd70e",
|
||||
"status": 200,
|
||||
"bytes": 1050
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/async-guard.js?v=e4afa1f2be",
|
||||
"status": 200,
|
||||
"bytes": 725
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/asset-sync-core.js?v=155be9339b",
|
||||
"status": 200,
|
||||
"bytes": 1690
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/sw-update.js?v=772c123c20",
|
||||
"status": 200,
|
||||
"bytes": 4411
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/related-videos.js?v=3eec0ebd4c",
|
||||
"status": 200,
|
||||
"bytes": 545
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/audio-continuity.js?v=63b5464dd5",
|
||||
"status": 200,
|
||||
"bytes": 583
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/fullscreen-orientation.js?v=c8e44eb66b",
|
||||
"status": 200,
|
||||
"bytes": 2494
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/settings-sections.js?v=1101425859",
|
||||
"status": 200,
|
||||
"bytes": 2690
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/download-actions.js?v=388c7edecb",
|
||||
"status": 200,
|
||||
"bytes": 550
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/download-errors.js?v=bb6a4c887a",
|
||||
"status": 200,
|
||||
"bytes": 727
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/downloads.js?v=f2d3e7d212",
|
||||
"status": 200,
|
||||
"bytes": 1764
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/downloads-page.js?v=c1a3a218c0",
|
||||
"status": 200,
|
||||
"bytes": 3103
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/saved-page.js?v=f1518c50fb",
|
||||
"status": 200,
|
||||
"bytes": 652
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/server-backfill.js?v=294b103023",
|
||||
"status": 200,
|
||||
"bytes": 918
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/visible-timer.js?v=5322e86ef4",
|
||||
"status": 200,
|
||||
"bytes": 380
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/prewarm-next.js?v=ed16a51424",
|
||||
"status": 200,
|
||||
"bytes": 567
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/eq-parameters.js?v=dc2c6a8e8d",
|
||||
"status": 200,
|
||||
"bytes": 722
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/feature-bootstrap.js?v=33779ecef7",
|
||||
"status": 200,
|
||||
"bytes": 2056
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/shell-core.js?v=a04305c2ad",
|
||||
"status": 200,
|
||||
"bytes": 3882
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/views-core.js?v=49be16274c",
|
||||
"status": 200,
|
||||
"bytes": 16310
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/section-rail.js?v=07417c1bcc",
|
||||
"status": 200,
|
||||
"bytes": 3552
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/app.js?v=f485286cbc",
|
||||
"status": 200,
|
||||
"bytes": 95477
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/api/recommendations?fp=c83c12c79b483c87",
|
||||
"status": 200,
|
||||
"bytes": 24
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/api/version",
|
||||
"status": 200,
|
||||
"bytes": 62
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/sw.js",
|
||||
"status": 200,
|
||||
"bytes": 7766
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/api/user/sync",
|
||||
"status": 200,
|
||||
"bytes": 11
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/asset-sync-core.js?v=155be9339b",
|
||||
"status": 304,
|
||||
"bytes": 0
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/api/manifest",
|
||||
"status": 200,
|
||||
"bytes": 3210
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/assets.json?v=6f517e2aa4",
|
||||
"status": 200,
|
||||
"bytes": 1058
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/fonts/BricolageGrotesque-latin-ext.woff2",
|
||||
"status": 200,
|
||||
"bytes": 30736
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/fonts/HankenGrotesk-latin-ext.woff2",
|
||||
"status": 200,
|
||||
"bytes": 19588
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/fonts/JetBrainsMono-latin-ext.woff2",
|
||||
"status": 200,
|
||||
"bytes": 11624
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/fonts/JetBrainsMono-latin.woff2",
|
||||
"status": 200,
|
||||
"bytes": 31432
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/fonts/fonts.css",
|
||||
"status": 200,
|
||||
"bytes": 391
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/icons/icon-192.png",
|
||||
"status": 200,
|
||||
"bytes": 1669
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/icons/icon-512.png",
|
||||
"status": 200,
|
||||
"bytes": 4609
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/index.html?v=b556b50667",
|
||||
"status": 200,
|
||||
"bytes": 11441
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/manifest.webmanifest",
|
||||
"status": 200,
|
||||
"bytes": 631
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/opfs-worker.js?v=17cfe8fb26",
|
||||
"status": 200,
|
||||
"bytes": 3487
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/api/recommendations?fp=c83c12c79b483c87",
|
||||
"status": 200,
|
||||
"bytes": 24
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/resume-core.js?v=df42e94600",
|
||||
"status": 200,
|
||||
"bytes": 762
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/sw.js",
|
||||
"status": 200,
|
||||
"bytes": 7766
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/asset-sync-core.js?v=155be9339b",
|
||||
"status": 304,
|
||||
"bytes": 0
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/bento-hub.js?v=c867882d7e",
|
||||
"status": 200,
|
||||
"bytes": 1294
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/car-mode.css?v=7d421630b3",
|
||||
"status": 200,
|
||||
"bytes": 385
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/car-mode.js?v=ebd6588f35",
|
||||
"status": 200,
|
||||
"bytes": 1727
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/direct-media.css?v=19b8428bfd",
|
||||
"status": 200,
|
||||
"bytes": 291
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/direct-media.js?v=035420e8fb",
|
||||
"status": 200,
|
||||
"bytes": 3697
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/direct-protocol.js?v=87a73be90f",
|
||||
"status": 200,
|
||||
"bytes": 1079
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/eq-core.js?v=cb6d079933",
|
||||
"status": 200,
|
||||
"bytes": 875
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/direct-recv-worker.js?v=caa45eb981",
|
||||
"status": 200,
|
||||
"bytes": 1050
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/direct-stream.js?v=d7f9871605",
|
||||
"status": 200,
|
||||
"bytes": 1249
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/f7-layout.js?v=fe7e94a4a9",
|
||||
"status": 200,
|
||||
"bytes": 4158
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/fonts/PlusJakartaSans-latin-ext.woff2?v=38e3b8fd80",
|
||||
"status": 200,
|
||||
"bytes": 21728
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/fonts/PlusJakartaSans-latin.woff2?v=153fc85b70",
|
||||
"status": 200,
|
||||
"bytes": 27348
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/export.js?v=5b7cdcd7a3",
|
||||
"status": 200,
|
||||
"bytes": 1305
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/glass-controls.js?v=a60ed1fe84",
|
||||
"status": 200,
|
||||
"bytes": 2763
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/glass-panel-layout.js?v=d5417786d0",
|
||||
"status": 200,
|
||||
"bytes": 965
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/hash-worker.js?v=5cccc78057",
|
||||
"status": 200,
|
||||
"bytes": 542
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/lower-third.css?v=031f8e0ead",
|
||||
"status": 200,
|
||||
"bytes": 375
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/lower-third.js?v=7705dcbfb4",
|
||||
"status": 200,
|
||||
"bytes": 927
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/lyrics-window.js?v=8f333e2442",
|
||||
"status": 200,
|
||||
"bytes": 2048
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/p2p-transfer.js?v=e508302618",
|
||||
"status": 200,
|
||||
"bytes": 2431
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/p2p-core.js?v=168a879219",
|
||||
"status": 200,
|
||||
"bytes": 989
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/p2p-recv-worker.js?v=9d435c6cbb",
|
||||
"status": 200,
|
||||
"bytes": 1267
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/midi.js?v=dbecfa74e1",
|
||||
"status": 200,
|
||||
"bytes": 1713
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/p2p-client.js?v=74fbd79661",
|
||||
"status": 200,
|
||||
"bytes": 3850
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/piano-engine.mjs?v=2d2f29b38e",
|
||||
"status": 200,
|
||||
"bytes": 2580
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/piano-core.js?v=77c8269761",
|
||||
"status": 200,
|
||||
"bytes": 756
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/piano.js?v=e82bc30884",
|
||||
"status": 200,
|
||||
"bytes": 3453
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/presenter.js?v=e5b34ff758",
|
||||
"status": 200,
|
||||
"bytes": 3094
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/party-dj.js?v=1677c38a88",
|
||||
"status": 200,
|
||||
"bytes": 1184
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/remote-client.js?v=a2b5acb20f",
|
||||
"status": 200,
|
||||
"bytes": 7926
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/setlist-import.js?v=13bc5cc4a4",
|
||||
"status": 200,
|
||||
"bytes": 2462
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/stats-core.js?v=3de0591d83",
|
||||
"status": 200,
|
||||
"bytes": 2336
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/share-external.js?v=9de67de710",
|
||||
"status": 200,
|
||||
"bytes": 3653
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/theme-f7.css?v=02ba226f82",
|
||||
"status": 200,
|
||||
"bytes": 4727
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/theme-glass-controls.css?v=3354ad9631",
|
||||
"status": 200,
|
||||
"bytes": 1480
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/theme-glass-panel.css?v=25aadb0bb7",
|
||||
"status": 200,
|
||||
"bytes": 848
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/stats-view.js?v=beb2343b30",
|
||||
"status": 200,
|
||||
"bytes": 2294
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/theme-bento-hub.css?v=f529dc4bb7",
|
||||
"status": 200,
|
||||
"bytes": 6718
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/vendor/framework7-swipe.min.js?v=22b954749c",
|
||||
"status": 200,
|
||||
"bytes": 38592
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/vocal-reducer.js?v=ddb2fc1bbe",
|
||||
"status": 200,
|
||||
"bytes": 1146
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/video-edit.js?v=90c5dd1eb6",
|
||||
"status": 200,
|
||||
"bytes": 2168
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/watch-party-client.js?v=0210655848",
|
||||
"status": 200,
|
||||
"bytes": 6513
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/theme-glass.css?v=09feb15c53",
|
||||
"status": 200,
|
||||
"bytes": 5068
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/api/p2p/config",
|
||||
"status": 200,
|
||||
"bytes": 40
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/api/p2p/device",
|
||||
"status": 200,
|
||||
"bytes": 121
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/api/p2p/holdings",
|
||||
"status": 200,
|
||||
"bytes": 54
|
||||
}
|
||||
],
|
||||
"initialJsCss": {
|
||||
"median": 210419,
|
||||
"min": 210419,
|
||||
"max": 210419,
|
||||
"values": [
|
||||
210419,
|
||||
210419,
|
||||
210419
|
||||
]
|
||||
},
|
||||
"initialAssetRequests": [
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/lazy.js?v=99caff8ebd",
|
||||
"bytes": 2543
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/theme-classic.css?v=d420fcfb12",
|
||||
"bytes": 3529
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/fonts/fonts.css?v=dda3dfb804",
|
||||
"bytes": 391
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/styles.css?v=9f3a5dea41",
|
||||
"bytes": 27364
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/service-ui.css?v=b9bf96a3a8",
|
||||
"bytes": 3736
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/refresh.css?v=62498384f1",
|
||||
"bytes": 5027
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/layout-base.css?v=4f3307cd3b",
|
||||
"bytes": 278
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/recommendations.css?v=055101368d",
|
||||
"bytes": 790
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/settings-sections.css?v=055507ab85",
|
||||
"bytes": 873
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/offline-pages.css?v=2889456261",
|
||||
"bytes": 859
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/saved-page.css?v=3ff576a784",
|
||||
"bytes": 537
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/fullscreen-orientation.css?v=91f2d84453",
|
||||
"bytes": 1415
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/related-videos.css?v=5a616b1be8",
|
||||
"bytes": 404
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/download-actions.css?v=12d3bcfe3e",
|
||||
"bytes": 430
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/fingerprint.js?v=a635143269",
|
||||
"bytes": 1034
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/opfs.js?v=df7a8d0391",
|
||||
"bytes": 3920
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/lyrics-core.js?v=4dcdac2edd",
|
||||
"bytes": 2632
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/lyrics-display.js?v=48e8550175",
|
||||
"bytes": 571
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/flag-ui.js?v=eeae1c1d1a",
|
||||
"bytes": 2036
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/sha256-wasm.js?v=393c50ba56",
|
||||
"bytes": 1521
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/sha256.js?v=cd9b980e6f",
|
||||
"bytes": 2733
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/loudness-wasm.js?v=c6102d7844",
|
||||
"bytes": 1130
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/loudness.js?v=01b3da88dd",
|
||||
"bytes": 1818
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/device-db.js?v=880c5cd70e",
|
||||
"bytes": 1050
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/async-guard.js?v=e4afa1f2be",
|
||||
"bytes": 725
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/asset-sync-core.js?v=155be9339b",
|
||||
"bytes": 1690
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/sw-update.js?v=772c123c20",
|
||||
"bytes": 4411
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/related-videos.js?v=3eec0ebd4c",
|
||||
"bytes": 545
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/audio-continuity.js?v=63b5464dd5",
|
||||
"bytes": 583
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/fullscreen-orientation.js?v=c8e44eb66b",
|
||||
"bytes": 2494
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/settings-sections.js?v=1101425859",
|
||||
"bytes": 2690
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/download-actions.js?v=388c7edecb",
|
||||
"bytes": 550
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/download-errors.js?v=bb6a4c887a",
|
||||
"bytes": 727
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/downloads.js?v=f2d3e7d212",
|
||||
"bytes": 1764
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/downloads-page.js?v=c1a3a218c0",
|
||||
"bytes": 3103
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/saved-page.js?v=f1518c50fb",
|
||||
"bytes": 652
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/server-backfill.js?v=294b103023",
|
||||
"bytes": 918
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/visible-timer.js?v=5322e86ef4",
|
||||
"bytes": 380
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/prewarm-next.js?v=ed16a51424",
|
||||
"bytes": 567
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/eq-parameters.js?v=dc2c6a8e8d",
|
||||
"bytes": 722
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/feature-bootstrap.js?v=33779ecef7",
|
||||
"bytes": 2056
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/shell-core.js?v=a04305c2ad",
|
||||
"bytes": 3882
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/views-core.js?v=49be16274c",
|
||||
"bytes": 16310
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/section-rail.js?v=07417c1bcc",
|
||||
"bytes": 3552
|
||||
},
|
||||
{
|
||||
"url": "http://127.0.0.1:6199/app.js?v=f485286cbc",
|
||||
"bytes": 95477
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2619
perf/results/phase4-final-2026-10-08.json
Normal file
2619
perf/results/phase4-final-2026-10-08.json
Normal file
File diff suppressed because it is too large
Load Diff
133
perf/results/phase4-hashing-rollback-2026-10-08.json
Normal file
133
perf/results/phase4-hashing-rollback-2026-10-08.json
Normal file
@@ -0,0 +1,133 @@
|
||||
{
|
||||
"date": "2026-10-07T21:00:01.096Z",
|
||||
"frontendCommit": null,
|
||||
"frontendBuildTag": "1146a2a9ceca",
|
||||
"commit": "2c5003575c641fddb128c6d1d14bb5d1e3999efb",
|
||||
"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": 48,
|
||||
"min": 48,
|
||||
"max": 48,
|
||||
"values": [
|
||||
48
|
||||
]
|
||||
},
|
||||
"lcp": {
|
||||
"median": 48,
|
||||
"min": 48,
|
||||
"max": 48,
|
||||
"values": [
|
||||
48
|
||||
]
|
||||
},
|
||||
"domContentLoaded": {
|
||||
"median": 152,
|
||||
"min": 152,
|
||||
"max": 152,
|
||||
"values": [
|
||||
152
|
||||
]
|
||||
},
|
||||
"bootDone": {
|
||||
"median": 156,
|
||||
"min": 156,
|
||||
"max": 156,
|
||||
"values": [
|
||||
156
|
||||
]
|
||||
},
|
||||
"reloadDuration": {
|
||||
"median": 173,
|
||||
"min": 173,
|
||||
"max": 173,
|
||||
"values": [
|
||||
173
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"webkit": {
|
||||
"lte": {
|
||||
"offline": {
|
||||
"requestCount": {
|
||||
"median": 0,
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"values": [
|
||||
0
|
||||
]
|
||||
},
|
||||
"wireBytes": {
|
||||
"median": 0,
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"values": [
|
||||
0
|
||||
]
|
||||
},
|
||||
"fcp": {
|
||||
"median": 53,
|
||||
"min": 53,
|
||||
"max": 53,
|
||||
"values": [
|
||||
53
|
||||
]
|
||||
},
|
||||
"lcp": {
|
||||
"median": 81,
|
||||
"min": 81,
|
||||
"max": 81,
|
||||
"values": [
|
||||
81
|
||||
]
|
||||
},
|
||||
"domContentLoaded": {
|
||||
"median": 80,
|
||||
"min": 80,
|
||||
"max": 80,
|
||||
"values": [
|
||||
80
|
||||
]
|
||||
},
|
||||
"bootDone": {
|
||||
"median": 83,
|
||||
"min": 83,
|
||||
"max": 83,
|
||||
"values": [
|
||||
83
|
||||
]
|
||||
},
|
||||
"reloadDuration": {
|
||||
"median": 100,
|
||||
"min": 100,
|
||||
"max": 100,
|
||||
"values": [
|
||||
100
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
79
perf/results/phase4-lazy-2026-10-08.json
Normal file
79
perf/results/phase4-lazy-2026-10-08.json
Normal file
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"browser": "chromium",
|
||||
"sourceBuildTag": "09d1ee0f9c80",
|
||||
"classicSharedDefaults": true,
|
||||
"cssOrderPreserved": true,
|
||||
"settingsSearch": true,
|
||||
"carControls": 4,
|
||||
"offlineFeature": true,
|
||||
"firstUseNetwork": 0,
|
||||
"layoutsOffline": [
|
||||
"glass-stage",
|
||||
"bento-hub",
|
||||
"f7-swipe",
|
||||
"classic"
|
||||
],
|
||||
"pinned": true,
|
||||
"compatibleUnexecutedNewURL": true,
|
||||
"incompatibleN1ReloadRequired": true,
|
||||
"stagedN1": true,
|
||||
"playbackGuard": true,
|
||||
"prePaintLayout": true,
|
||||
"offlineSettingsPanels": true,
|
||||
"scriptErrors": [],
|
||||
"offlineTransportErrors": []
|
||||
},
|
||||
{
|
||||
"browser": "webkit",
|
||||
"sourceBuildTag": "09d1ee0f9c80",
|
||||
"classicSharedDefaults": true,
|
||||
"cssOrderPreserved": true,
|
||||
"settingsSearch": true,
|
||||
"carControls": 4,
|
||||
"offlineFeature": true,
|
||||
"firstUseNetwork": 0,
|
||||
"layoutsOffline": [
|
||||
"glass-stage",
|
||||
"bento-hub",
|
||||
"f7-swipe",
|
||||
"classic"
|
||||
],
|
||||
"pinned": true,
|
||||
"compatibleUnexecutedNewURL": true,
|
||||
"incompatibleN1ReloadRequired": true,
|
||||
"stagedN1": true,
|
||||
"playbackGuard": true,
|
||||
"prePaintLayout": true,
|
||||
"offlineSettingsPanels": true,
|
||||
"scriptErrors": [],
|
||||
"offlineTransportErrors": [
|
||||
{
|
||||
"message": "TypeError: Load failed",
|
||||
"disconnected": true
|
||||
},
|
||||
{
|
||||
"message": "/127.0.0.1:38295/api/version.",
|
||||
"disconnected": true
|
||||
},
|
||||
{
|
||||
"message": "TypeError: Load failed",
|
||||
"disconnected": true
|
||||
},
|
||||
{
|
||||
"message": "/127.0.0.1:38295/api/recommendations?fp=163577c02a53bc40.",
|
||||
"disconnected": true
|
||||
},
|
||||
{
|
||||
"message": "TypeError: Load failed",
|
||||
"disconnected": true
|
||||
},
|
||||
{
|
||||
"message": "/127.0.0.1:38295/api/version.",
|
||||
"disconnected": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
41
perf/results/phase4-migration-lossy-2026-10-08.json
Normal file
41
perf/results/phase4-migration-lossy-2026-10-08.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"commit": "b77938a",
|
||||
"results": [
|
||||
{
|
||||
"browser": "chromium",
|
||||
"oldTag": "1175f1a1d2c1",
|
||||
"newTag": "c3dbdd7039db",
|
||||
"banners": 1,
|
||||
"updateReloads": 1,
|
||||
"cachedFiles": 122,
|
||||
"durationMs": 25699,
|
||||
"wireBytes": 628797,
|
||||
"offline": true,
|
||||
"legacyURLs": 21,
|
||||
"profile": "lossy",
|
||||
"userInitiatedOnly": true,
|
||||
"playbackGuard": true,
|
||||
"evictionRepair": true,
|
||||
"incrementalRefresh": true,
|
||||
"offlineTransportErrors": 0
|
||||
},
|
||||
{
|
||||
"browser": "webkit",
|
||||
"oldTag": "1175f1a1d2c1",
|
||||
"newTag": "c3dbdd7039db",
|
||||
"banners": 1,
|
||||
"updateReloads": 1,
|
||||
"cachedFiles": 122,
|
||||
"durationMs": 23376,
|
||||
"wireBytes": 737972,
|
||||
"offline": true,
|
||||
"legacyURLs": 21,
|
||||
"profile": "lossy",
|
||||
"userInitiatedOnly": true,
|
||||
"playbackGuard": true,
|
||||
"evictionRepair": true,
|
||||
"incrementalRefresh": true,
|
||||
"offlineTransportErrors": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
41
perf/results/phase4-migration-unthrottled-2026-10-08.json
Normal file
41
perf/results/phase4-migration-unthrottled-2026-10-08.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"commit": "b77938a",
|
||||
"results": [
|
||||
{
|
||||
"browser": "chromium",
|
||||
"oldTag": "1175f1a1d2c1",
|
||||
"newTag": "c3dbdd7039db",
|
||||
"banners": 1,
|
||||
"updateReloads": 1,
|
||||
"cachedFiles": 122,
|
||||
"durationMs": 9805,
|
||||
"wireBytes": 646234,
|
||||
"offline": true,
|
||||
"legacyURLs": 21,
|
||||
"profile": "unthrottled",
|
||||
"userInitiatedOnly": true,
|
||||
"playbackGuard": true,
|
||||
"evictionRepair": true,
|
||||
"incrementalRefresh": true,
|
||||
"offlineTransportErrors": 0
|
||||
},
|
||||
{
|
||||
"browser": "webkit",
|
||||
"oldTag": "1175f1a1d2c1",
|
||||
"newTag": "c3dbdd7039db",
|
||||
"banners": 1,
|
||||
"updateReloads": 1,
|
||||
"cachedFiles": 122,
|
||||
"durationMs": 9554,
|
||||
"wireBytes": 751943,
|
||||
"offline": true,
|
||||
"legacyURLs": 21,
|
||||
"profile": "unthrottled",
|
||||
"userInitiatedOnly": true,
|
||||
"playbackGuard": true,
|
||||
"evictionRepair": true,
|
||||
"incrementalRefresh": true,
|
||||
"offlineTransportErrors": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
28
perf/results/phase4-seams-2026-10-08.json
Normal file
28
perf/results/phase4-seams-2026-10-08.json
Normal file
@@ -0,0 +1,28 @@
|
||||
[
|
||||
{
|
||||
"browser": "chromium",
|
||||
"checked": [
|
||||
"shell",
|
||||
"presenter",
|
||||
"remote",
|
||||
"party",
|
||||
"share",
|
||||
"stats"
|
||||
],
|
||||
"offlineNetworkRequests": 0,
|
||||
"errors": []
|
||||
},
|
||||
{
|
||||
"browser": "webkit",
|
||||
"checked": [
|
||||
"shell",
|
||||
"presenter",
|
||||
"remote",
|
||||
"party",
|
||||
"share",
|
||||
"stats"
|
||||
],
|
||||
"offlineNetworkRequests": 0,
|
||||
"errors": []
|
||||
}
|
||||
]
|
||||
133
perf/results/phase4-sync-rollback-2026-10-08.json
Normal file
133
perf/results/phase4-sync-rollback-2026-10-08.json
Normal file
@@ -0,0 +1,133 @@
|
||||
{
|
||||
"date": "2026-10-07T20:58:10.947Z",
|
||||
"frontendCommit": null,
|
||||
"frontendBuildTag": "9b741452f44e",
|
||||
"commit": "2c5003575c641fddb128c6d1d14bb5d1e3999efb",
|
||||
"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": 40,
|
||||
"min": 40,
|
||||
"max": 40,
|
||||
"values": [
|
||||
40
|
||||
]
|
||||
},
|
||||
"lcp": {
|
||||
"median": 40,
|
||||
"min": 40,
|
||||
"max": 40,
|
||||
"values": [
|
||||
40
|
||||
]
|
||||
},
|
||||
"domContentLoaded": {
|
||||
"median": 136,
|
||||
"min": 136,
|
||||
"max": 136,
|
||||
"values": [
|
||||
136
|
||||
]
|
||||
},
|
||||
"bootDone": {
|
||||
"median": 137,
|
||||
"min": 137,
|
||||
"max": 137,
|
||||
"values": [
|
||||
137
|
||||
]
|
||||
},
|
||||
"reloadDuration": {
|
||||
"median": 154,
|
||||
"min": 154,
|
||||
"max": 154,
|
||||
"values": [
|
||||
154
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"webkit": {
|
||||
"lte": {
|
||||
"offline": {
|
||||
"requestCount": {
|
||||
"median": 0,
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"values": [
|
||||
0
|
||||
]
|
||||
},
|
||||
"wireBytes": {
|
||||
"median": 0,
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"values": [
|
||||
0
|
||||
]
|
||||
},
|
||||
"fcp": {
|
||||
"median": 60,
|
||||
"min": 60,
|
||||
"max": 60,
|
||||
"values": [
|
||||
60
|
||||
]
|
||||
},
|
||||
"lcp": {
|
||||
"median": 96,
|
||||
"min": 96,
|
||||
"max": 96,
|
||||
"values": [
|
||||
96
|
||||
]
|
||||
},
|
||||
"domContentLoaded": {
|
||||
"median": 94,
|
||||
"min": 94,
|
||||
"max": 94,
|
||||
"values": [
|
||||
94
|
||||
]
|
||||
},
|
||||
"bootDone": {
|
||||
"median": 98,
|
||||
"min": 98,
|
||||
"max": 98,
|
||||
"values": [
|
||||
98
|
||||
]
|
||||
},
|
||||
"reloadDuration": {
|
||||
"median": 115,
|
||||
"min": 115,
|
||||
"max": 115,
|
||||
"values": [
|
||||
115
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ async function run(name){
|
||||
browser=await ({chromium,webkit}[name]).launch({headless:true});const context=await browser.newContext();
|
||||
await context.route('**/*',r=>r.request().url().startsWith(origin)?r.continue():r.abort());
|
||||
await context.addInitScript(()=>{Object.defineProperty(navigator,'onLine',{configurable:true,get:()=>!window.__offline});});
|
||||
const page=await context.newPage(),errors=[];page.on('pageerror',e=>errors.push(e.message));
|
||||
const page=await context.newPage(),errors=[],failedRequests=[];page.on('pageerror',e=>errors.push(e.message));page.on('requestfailed',r=>failedRequests.push(r.url()));
|
||||
await page.goto(origin);await page.waitForFunction(()=>typeof data!=='undefined'&&document.querySelector('#carModeBtn'));
|
||||
await wait(page,async()=>!!(await navigator.serviceWorker.getRegistration())?.active);
|
||||
await page.evaluate(()=>Lazy.warm());
|
||||
@@ -39,14 +39,18 @@ async function run(name){
|
||||
const checked=['shell'];
|
||||
if(groups.includes('feature:presenter')) {
|
||||
await page.evaluate(async()=>{history.replaceState(null,'','/?present=');await Presenter.boot();});
|
||||
await page.waitForSelector('#presenterView:not(.hidden)');await page.keyboard.press('b');
|
||||
await page.waitForSelector('#presenterView:not(.hidden)');
|
||||
await page.locator('#pvCode').fill('x');await page.locator('#pvPairBtn').click();assert.match(await page.locator('#pvMsg').textContent(),/6-digit/);
|
||||
await page.evaluate(()=>document.activeElement?.blur());await page.keyboard.press('b');
|
||||
assert.equal(await page.locator('#pvBlank').evaluate(n=>!n.classList.contains('hidden')),true);
|
||||
await page.evaluate(()=>{document.querySelector('#presenterView').classList.add('hidden');document.body.classList.remove('presenter-open');});checked.push('presenter');
|
||||
}
|
||||
if(groups.includes('feature:remote-client')) {
|
||||
await page.evaluate(()=>document.querySelector('#navRemoteBtn').click());
|
||||
await page.waitForSelector('#modal:not(.hidden)');assert.match(await page.locator('#modal').textContent(),/remote|screen|phone/i);
|
||||
await page.evaluate(()=>closeModal());checked.push('remote');
|
||||
await page.getByRole('button',{name:'Use this phone as a remote',exact:true}).click();
|
||||
await page.waitForSelector('#remoteView:not(.hidden)');await page.locator('#rvCode').fill('x');await page.locator('#rvPairBtn').click();
|
||||
assert.match(await page.locator('#rvPairMsg').textContent(),/6-digit/);await page.locator('#rvClose').click();checked.push('remote');
|
||||
}
|
||||
if(groups.includes('feature:watch-party')) {
|
||||
await page.evaluate(()=>document.querySelector('#navPartyBtn').click());await page.waitForSelector('#partyPanel:not(.hidden)');
|
||||
@@ -58,10 +62,14 @@ async function run(name){
|
||||
await page.locator('.sm-time').fill('0:30');await page.locator('.sm-time').dispatchEvent('input');
|
||||
assert.match(await page.locator('.sm-app').textContent(),/t=30/);
|
||||
const m3u=await page.evaluate(async()=>{await Lazy.load('feature:share-external');return window.YT.External.m3u([{id:'benchmedia01',title:'Cached smoke'}]);});assert.match(m3u,/#EXTM3U/);assert.match(m3u,/benchmedia01/);
|
||||
await page.evaluate(async()=>{closeModal();current={meta:{id:'upl_0123456789ab',title:'Cached upload'}};await External.open();});
|
||||
await page.waitForSelector('.ext-panel');assert.match(await page.locator('.ext-panel').textContent(),/api\/uploads\/upl_0123456789ab/);
|
||||
await page.evaluate(()=>closeModal());checked.push('share');
|
||||
}
|
||||
if(groups.includes('feature:stats-view')) {
|
||||
await page.evaluate(async()=>{view={type:'stats'};render();});await page.waitForSelector('.stats-empty');checked.push('stats');
|
||||
await page.evaluate(async()=>{view={type:'stats'};render();});await page.waitForSelector('.stats-empty');
|
||||
await page.evaluate(async()=>{data.stats=StatsCore.record(null,{id:'benchmedia01',title:'Cached stats',channel:'Fixture'},600,true);await renderStats();});
|
||||
await page.waitForSelector('.stats .st-tiles');assert.match(await page.locator('.st-song-text').first().textContent(),/Cached stats/);checked.push('stats');
|
||||
}
|
||||
if(groups.includes('feature:share-external')) {
|
||||
await page.evaluate(()=>{Share.open=()=>Promise.reject(new Error('Unavailable fixture chunk'));document.querySelector('#shareMomentBtn').click();});
|
||||
@@ -70,6 +78,7 @@ async function run(name){
|
||||
assert.equal(proxy.getStats().requestCount,before,'all warmed seam code loads from SW without network');
|
||||
// Ignore only verified disconnected version/recommendation API transports in WebKit.
|
||||
const scriptErrors=errors.filter(e=>!(name==='webkit'&&(e==='TypeError: Load failed'||/\/api\/(?:recommendations\?[^\s]*|version)\.$/.test(e))));assert.deepEqual(scriptErrors,[]);
|
||||
if(errors.length>scriptErrors.length)assert.ok(failedRequests.some(url=>/\/api\/(?:recommendations|version)/.test(url)),'ignored WebKit transport errors require a recorded disconnected API request');
|
||||
results.push({browser:name,checked,offlineNetworkRequests:proxy.getStats().requestCount-before,errors:scriptErrors});console.log(name,JSON.stringify(results.at(-1)));
|
||||
}finally{await browser?.close();await stop();await proxy?.close();}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Source: `cd4a25a`, 587,029 bytes. Acorn 8 parses classic scripts with source ranges; eslint-scope 8 resolves lexical references, including shadowing. Outside references are references outside the declaration’s owning top-level statement, plus unresolved references from other frontend classic scripts. Property names and strings are not lexical references. Browser globals and other scripts’ globals remain available. Positions below refer to this source, before extraction.
|
||||
|
||||
Reproduce: `npm install --prefix perf/.tmp/analysis --no-audit --no-fund acorn@8 eslint-scope@8`, then run `node perf/analyze-app.cjs`. Analysis tools are development-only; no frontend/server import is added.
|
||||
Reproduce: `npm install --prefix perf/.tmp/analysis --no-audit --no-fund acorn@8 eslint-scope@8`, then run `node perf/analyze-app.cjs cd4a25a`. Analysis tools are development-only; no frontend/server import is added.
|
||||
|
||||
## Measured candidate ranking
|
||||
|
||||
@@ -414,3 +414,34 @@ Outside references use app line numbers or `file:line`; imports name other app b
|
||||
| bootViewFromUrl | 12531 | 391 | view, render, URL_VIEWS | 12625 |
|
||||
| bootSearchFromUrl | 12545 | 414 | els | 12626 |
|
||||
| boot | 12563 | 11475 | WEB, APP_VERSION, perfMark, perfMeasure, webFetch, SaveQueue, API, DEFAULT_SETTINGS, data, view, current, abA, abB, cachedIds, downloading, $, els, persist, ProfileSecret, profileHeaders, syncOnLaunch, updateProfileStatus, adoptSharedPlaylistFromUrl, startPlaylistInboxWatch, adoptProfileFromUrl, syncMuteIcon, toast, uid, applyAppearance, refreshCachedIds, startCacheResyncWatch, warmOfflineThumbs, preload, preloadPlaylist, preloadPinnedPlaylists, Player, wirePlayerEvents, updatePlayBtn, Notes, Remote, Transition, CatalogSync, Recommendations, Presenter, Share, EqRender, PiP, EQ, SectionRail, Party, updateBottomChrome, updateQueueBadge, playNext, updateLoopRepeatButtons, playPrev, isServiceModeOpen, renderSidebar, exportToDevice, render, slim, wireShortcutHelp, showModal, closeModal, setupClassicLayout, setupPortraitPwaWatcher, setupViewportAnchorGuard, wireUI, setAbA, setAbB, clearAb, saveAbMarkers, updateAbUI, renderSmartSidebar, checkAutoBackup, checkBuildTag, pollBuildTag, checkUpdateOutcome, registerServiceWorker, bootShareFromUrl, bootViewFromUrl, bootSearchFromUrl | 12734 |
|
||||
|
||||
## Final cuts and review
|
||||
|
||||
Exactly six seams shipped: 3c9a24a (eager shell/shared renderers), 5fb9564
|
||||
(Presenter), 8e7fa19 (Remote), 94ea211 (Watch party), 0475a18 (Share/External),
|
||||
b335f95 (Stats view). 2c50035 handles lazy-entry failures without rejected UI
|
||||
navigation promises. Final app.js: 408,473 bytes; net removal 178,556 bytes
|
||||
(30.4169%), including 2,976 bytes of facade/call-site overhead.
|
||||
|
||||
Original bytes moved, independently counted from UTF-8 AST source slices:
|
||||
98,378 eager renderer/shell/rail; 9,492 Presenter; 30,421 Remote;
|
||||
22,833 Party; 13,334 Share/External; 7,074 Stats view. Published files include
|
||||
headers/registry wrappers. Shared functions retain classic global lexical access;
|
||||
new UI definitions evaluate safely before data/$/els/Player initialization.
|
||||
|
||||
Self-review against master §6/6b: all new files belong to explicit manifest
|
||||
groups and legacy SHELL; source JSON matches assets.json; core scripts load first;
|
||||
required eager features stay parsed. Player, Transition, Wave, EQ/level rendering,
|
||||
queue, persistence, tracking and sleep bodies have exact source fingerprint tests.
|
||||
Transport internals move intact; entry button bindings move to core facades to
|
||||
avoid duplicate listeners. Inbound APIs remain short; synchronous boolean/hooks
|
||||
never become promises. Boot URL/session triggers remain; no banner/cache-header
|
||||
rule is changed. Executing groups remain pinned; no disposal/handoff or live
|
||||
replacement is introduced. Contract/N-1 safeguards remain tested by existing
|
||||
unit/integration checks.
|
||||
|
||||
Deliberately left: Notes/editor, service mode, playlist mutations, persistence,
|
||||
player/queue/boot, audio watchdogs/EQ/sleep, Gestures, video editor/export glue and
|
||||
other candidates beyond six seams. Settings paint moves to views-core but remains
|
||||
eager. Now-playing metadata mutations inside Player stay there to honor the
|
||||
untouched-playback constraint; their DOM, action paint and mini bar are eager.
|
||||
|
||||
119
plans/phase4-verification.md
Normal file
119
plans/phase4-verification.md
Normal file
@@ -0,0 +1,119 @@
|
||||
# Phase 4 verification
|
||||
|
||||
The served frontend is build `c3dbdd7039db`, source delivery commit `2c50035`.
|
||||
`phase4-final-2026-10-08.json` records parent b335f95 because the review fix was
|
||||
uncommitted when its scratch tree was copied; that tree includes exactly the
|
||||
frontend subsequently committed as 2c50035. The isolated cold result records both
|
||||
2c50035 and the build tag. Earlier phase result files were restored after harnesses
|
||||
wrote their default paths; Phase 4 copies retain the actual new run evidence.
|
||||
|
||||
## Six green seams
|
||||
|
||||
| Commit | Seam | Original bytes moved | Frontend tests | Server tests | Both-engine cached smoke / hidden timers |
|
||||
|---|---|---:|---:|---:|---|
|
||||
| 3c9a24a | Eager shell/views/section rail | 98,378 | 192 | 183 | Pass |
|
||||
| 5fb9564 | Presenter | 9,492 | 193 | 183 | Pass |
|
||||
| 8e7fa19 | Remote client | 30,421 | 194 | 183 | Pass |
|
||||
| 94ea211 | Watch party | 22,833 | 195 | 183 | Pass |
|
||||
| 0475a18 | Share/External | 13,334 | 196 | 183 | Pass |
|
||||
| b335f95 | Stats view | 7,074 | 197 | 183 | Pass |
|
||||
| 2c50035 | Lazy-entry rejection handling | — | 198 | 183 | Pass |
|
||||
|
||||
After every seam, `node --test frontend/*.test.js`, `bun install` then `bun run test`
|
||||
in server, `node perf/hidden-timers.mjs`, and `node perf/seams.mjs --browser all`
|
||||
ran. Server tests used PATH="$PWD/../perf/.tmp/test-venv/bin:$PATH" so yt-dlp
|
||||
worker tests also ran, without skips. Logs are in gitignored perf/.tmp; representative
|
||||
actual output:
|
||||
|
||||
```
|
||||
ℹ tests 198
|
||||
ℹ pass 198
|
||||
ℹ fail 0
|
||||
ℹ skipped 0
|
||||
```
|
||||
|
||||
Server totals across its isolated test processes: 183 pass, 0 fail, 0 skip.
|
||||
|
||||
```
|
||||
chromium {"browser":"chromium","checked":["shell","presenter","remote","party","share","stats"],"offlineNetworkRequests":0,"errors":[]}
|
||||
webkit {"browser":"webkit","checked":["shell","presenter","remote","party","share","stats"],"offlineNetworkRequests":0,"errors":[]}
|
||||
Result: ALL ASSERTIONS PASSED
|
||||
```
|
||||
|
||||
The cache smoke stops Bun and blocks its proxy, then tests home playlists and eager
|
||||
Settings, Presenter blank/pair validation, Remote pair form/close, Party local UI,
|
||||
Share timestamp editing, External uploaded-media sheet/M3U, populated Stats view,
|
||||
and a rejected entry action. Network relays are still required to connect parties
|
||||
or remotes; offline verification proves cached code/UI, not offline relay service.
|
||||
Existing lazy harness passes offline layouts, first-use, Settings extensions,
|
||||
contract guards, pinned instances and update-during-playback on both engines.
|
||||
|
||||
One review smoke WebKit process terminated during concurrent browser checks; an
|
||||
isolated rerun and the final expanded both-engine smoke passed. Initial harness
|
||||
fixture errors (incorrect Settings selector, absent VM helper, timestamp format,
|
||||
hidden list pane) were corrected to exercise actual UI; no product tests were
|
||||
removed or weakened.
|
||||
|
||||
## Measurements
|
||||
|
||||
Actual commands:
|
||||
|
||||
```
|
||||
node perf/baseline.mjs --runs 1 --browser all --profile lte --scenario all --out perf/results/phase4-final-2026-10-08.json --compare perf/results/after-phase0-2026-10-07.json
|
||||
node perf/baseline.mjs --runs 3 --browser chromium --profile lte --scenario cold --out perf/results/phase4-cold-isolated-2026-10-08.json --compare perf/results/after-phase0-2026-10-07.json
|
||||
```
|
||||
|
||||
Full reduced run overlapped other checks; its Chromium long tasks were 495 ms.
|
||||
Repeat cold-only runs with no concurrent tests produced 297/274/275 ms (median
|
||||
275). Keep both results: neither is rewritten. WebKit lacks the long-task API.
|
||||
Historical Phase 0 is five-run data; these reduced measurements are directional.
|
||||
|
||||
| Metric | Phase 0 Chromium / WebKit | Phase 3 Chromium / WebKit | Phase 4 Chromium / WebKit |
|
||||
|---|---:|---:|---:|
|
||||
| Initial compressed JS/CSS | 276,414 / 338,940* | 221,307 / 274,813 | 210,419 / 255,200 |
|
||||
| Cold boot ms | 10,480 / 3,290 | 7,193 / 3,293 | 7,010** / 2,977 |
|
||||
| Cold FCP ms | 1,572 / 1,100 | 1,356 / 2,467 | 1,352** / 2,401 |
|
||||
| Cold long-task ms | 454 / unavailable | 287 / unavailable | 275** / unavailable |
|
||||
| Warm boot ms | 692 / 139 | 419 / 81 | 467 / 132 |
|
||||
| Offline boot ms | 259 / 137 | 166 / 84 | 180 / 90 |
|
||||
| Core app update wire bytes | 611,338 / 680,822 | 159,905 / 194,026 | 125,795 / 147,259 |
|
||||
| Inactive CSS blocking-readiness bytes | 611,476 / 680,831 | 29,724 / 28,082 | 30,263 / 28,713 |
|
||||
| Feature edit through actual idle cache fill | — | — | 33,408 / 41,364 |
|
||||
|
||||
*Matched Phase 0 source reconstructed in Phase 3; historical JSON lacks initial
|
||||
bytes. **Isolated three-run Chromium cold median. Other Phase 4 numbers are the
|
||||
one-run both-browser suite. Warm counters include unfinished initial idle caching.
|
||||
CSS readiness excludes its later background payload; it is not full update cost.
|
||||
WebKit first paint still fails the master no-regression target. Full five-run
|
||||
comparisons belong to Phase 5. Native iPhone timing/audio/quota is unverified.
|
||||
|
||||
Actual feature-update output:
|
||||
|
||||
```
|
||||
run 1/1: 33408 bytes, 8 reqs, dur=1376ms
|
||||
run 1/1: 41364 bytes, 7 reqs, dur=1358ms
|
||||
```
|
||||
|
||||
Only presenter.js application payload transfers (3,118 / 3,587 compressed bytes).
|
||||
Totals include changed stamped index, manifest, version checks, sw.js checks and
|
||||
WebKit's 1,954-byte sync-core worker import. No app.js, unchanged core views,
|
||||
fonts, icons or CSS transfer. The benchmark asserts this rather than inferring it
|
||||
from the lower total. Final app.js is 408,473 versus 587,029 bytes: −178,556,
|
||||
−30.4169%; original code moved totals 181,532, facade overhead 2,976 bytes.
|
||||
|
||||
## Migration, rollback and owner checks
|
||||
|
||||
Both engines pass b77938a migration with lossy/stalling and unthrottled proxies:
|
||||
122 cached SHELL entries, one banner and exactly one user-initiated reload,
|
||||
21 legacy URL checks, N-1 open-tab continuity, offline boot, playback guard,
|
||||
eviction repair and incremental refresh. Result JSON records the real runs.
|
||||
No automatic activation/reload or live singleton replacement is added.
|
||||
|
||||
Rollback ASSET_SYNC=0 and ASSET_HASHING=0 use the existing legacy path; commands
|
||||
and results are in perf/README.md and perf/results. No new feature flag.
|
||||
Revert an individual seam to restore its previous parsing behavior.
|
||||
|
||||
Owner must verify a real iPhone PWA: warm feature first-use, selected/offline layout,
|
||||
Presenter/Remote/Party sessions, update guard/override, locked audio 30 minutes,
|
||||
interruption/resume, saved OPFS music surviving cache quota pressure. Nothing was
|
||||
pushed, merged or deployed.
|
||||
Reference in New Issue
Block a user