mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 02:14:01 +00:00
merge main f13c60c into feat/voice-outlines
reconcile voice outlines with main f13c60c, retaining German/Japanese,
Operator HUD retirement and Context/Radio cleanup, named-building
containment, courtyard-hole, non-Latin identity, attribution, cancellation
and antimeridian repairs
keep outline callouts above the open voice preview when an above-panel
slot fits without colliding with another callout,
and clip the compact dock location label on narrow screens
This commit is contained in:
commit
578ebdc030
449 files changed
+30400
-3429
No files matched your search
@@ -10,12 +10,12 @@
|
||||
* page holds traffic's target response while the outline consumer subscribes,
|
||||
* proving that overlap still produces one application fetch and one decode.
|
||||
*
|
||||
* Acceptance is declared before measurement: cold outline decode, extraction,
|
||||
* and install must fit one 60 Hz frame at p95 (16.7 ms), no sample may create a
|
||||
* Acceptance records actual owned synchronous segments (16.7 ms each), full
|
||||
* eight-probe completion within 2 s, and separate inclusive latency. No sample may create a
|
||||
* >=50 ms Long Task, and neither the first nor second outline ask may fetch or
|
||||
* decode the traffic-warm tile again. The target tile's traffic-idle outline
|
||||
* projection must also fit one frame; unrelated traffic activation Long Tasks
|
||||
* are reported separately as baseline evidence.
|
||||
* decode the traffic-warm tile again. The first explicit cold ask's target
|
||||
* projection must fit one frame; Traffic does no outline projection and the
|
||||
* warm ask reuses it. Traffic activation Long Tasks are reported separately.
|
||||
*/
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs/promises';
|
||||
@@ -68,6 +68,91 @@ const measures = (entries, name) =>
|
||||
const sum = (values) => values.reduce((total, value) => total + value, 0);
|
||||
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
|
||||
// Numeric DEV evidence from the actual owners; waited frames are latency, not CPU.
|
||||
function workEvidence(entries, label) {
|
||||
const work = entries.filter(
|
||||
(entry) => entry.name === 'outlines:install-work',
|
||||
);
|
||||
assert.equal(work.length, 1, `${label}: one completed owned-work trace`);
|
||||
const trace = work[0].detail;
|
||||
assert.equal(
|
||||
trace?.status,
|
||||
'installed',
|
||||
`${label}: processed install required`,
|
||||
);
|
||||
assert.equal(trace.samplerStatus, 'installed');
|
||||
assert.equal(trace.rendererStatus, 'installed');
|
||||
assert.equal(trace.dropped, 0, `${label}: no lost work intervals`);
|
||||
assert.equal(trace.probes, 8, `${label}: all original probes required`);
|
||||
assert.ok(Number.isFinite(trace.timeOrigin));
|
||||
assert.ok(
|
||||
Number.isFinite(trace.samplerStart) && Number.isFinite(trace.completedAt),
|
||||
);
|
||||
assert.ok(
|
||||
Number.isFinite(trace.callerStart) &&
|
||||
trace.callerStart <= trace.samplerStart,
|
||||
);
|
||||
const phases = {
|
||||
'engine-schedule': 1,
|
||||
'ground-step': 8,
|
||||
'hybrid-complete': 1,
|
||||
'engine-process': 1,
|
||||
'engine-finalize': 1,
|
||||
'engine-settle': 1,
|
||||
};
|
||||
assert.equal(
|
||||
trace.slices?.length,
|
||||
13,
|
||||
`${label}: complete disjoint owner intervals`,
|
||||
);
|
||||
for (const [phase, count] of Object.entries(phases))
|
||||
assert.equal(
|
||||
trace.slices.filter((slice) => slice.phase === phase).length,
|
||||
count,
|
||||
`${label}: ${phase}`,
|
||||
);
|
||||
let end = -Infinity;
|
||||
const durations = trace.slices.map((slice) => {
|
||||
assert.ok(
|
||||
Number.isFinite(slice.start) &&
|
||||
Number.isFinite(slice.end) &&
|
||||
slice.end >= slice.start,
|
||||
);
|
||||
assert.ok(
|
||||
slice.start >= end,
|
||||
`${label}: no nested or double-counted owner intervals`,
|
||||
);
|
||||
end = slice.end;
|
||||
const duration = slice.end - slice.start;
|
||||
assert.ok(
|
||||
duration <= FRAME_BUDGET_MS,
|
||||
`${label}: ${slice.phase} work slice ${duration} exceeds ${FRAME_BUDGET_MS} ms`,
|
||||
);
|
||||
return duration;
|
||||
});
|
||||
const completionMs = trace.completedAt - trace.samplerStart;
|
||||
assert.ok(
|
||||
completionMs >= 0 && completionMs <= 2000,
|
||||
`${label}: processed completion ${completionMs} ms exceeds 2000 ms`,
|
||||
);
|
||||
// This sum describes owned tail work, never the complete browser task/frame.
|
||||
const tailStart = trace.slices
|
||||
.filter((slice) => slice.phase === 'ground-step')
|
||||
.at(-1).start;
|
||||
return {
|
||||
timeOrigin: trace.timeOrigin,
|
||||
slices: trace.slices,
|
||||
maxSliceMs: Math.max(...durations),
|
||||
ownedTailSumMs: trace.slices
|
||||
.filter((slice) => slice.start >= tailStart)
|
||||
.reduce((total, slice) => total + slice.end - slice.start, 0),
|
||||
completionMs,
|
||||
callerCompletionMs: trace.completedAt - trace.callerStart,
|
||||
probes: trace.probes,
|
||||
dropped: trace.dropped,
|
||||
};
|
||||
}
|
||||
|
||||
await fs.mkdir(path.dirname(OUTPUT), { recursive: true });
|
||||
|
||||
const browser = await puppeteer.launch({
|
||||
@@ -95,9 +180,11 @@ const report = {
|
||||
target: TARGET,
|
||||
targetPath: TARGET_PATH,
|
||||
acceptance: {
|
||||
coldCpuP95Ms: FRAME_BUDGET_MS,
|
||||
maxOwnedSliceMs: FRAME_BUDGET_MS,
|
||||
samplerCompletionMaxMs: 2000,
|
||||
legacyInclusive: 'reported-not-gated',
|
||||
maxLongTaskMs: LONG_TASK_MS,
|
||||
trafficIdleProjectionMaxMs: FRAME_BUDGET_MS,
|
||||
coldProjectionMaxMs: FRAME_BUDGET_MS,
|
||||
coldApplicationFetches: 0,
|
||||
coldOutlineTransferBytes: 0,
|
||||
coldDecodes: 0,
|
||||
@@ -119,8 +206,8 @@ function relevantMeasures(raw) {
|
||||
)
|
||||
.map((entry) => ({
|
||||
name: entry.name,
|
||||
ms: round(entry.duration),
|
||||
at: round(entry.startTime),
|
||||
ms: entry.duration,
|
||||
at: entry.startTime,
|
||||
detail: entry.detail || {},
|
||||
}));
|
||||
}
|
||||
@@ -152,51 +239,51 @@ async function beginOutline(page, label) {
|
||||
|
||||
async function settleOutline(page, label) {
|
||||
return page.evaluate(async (label) => {
|
||||
const result = await window.__qaOutlinePromise;
|
||||
let annotation = null;
|
||||
const deadline = performance.now() + 30_000;
|
||||
while (performance.now() < deadline) {
|
||||
annotation = (window.__gevAnnotations?.list?.() || []).find(
|
||||
(item) => item.label === label,
|
||||
);
|
||||
if (annotation && !annotation.pendingOutline) break;
|
||||
await new Promise((resolve) => setTimeout(resolve, 25));
|
||||
}
|
||||
if (!annotation || annotation.pendingOutline)
|
||||
throw new Error(`${label}: outline did not settle`);
|
||||
const { scene } = window.__godsEyeView.viewer;
|
||||
await new Promise((resolve) => {
|
||||
const timer = setTimeout(resolve, 1500);
|
||||
const remove = scene.postRender.addEventListener(() => {
|
||||
clearTimeout(timer);
|
||||
remove();
|
||||
resolve();
|
||||
});
|
||||
scene.requestRender();
|
||||
});
|
||||
await new Promise((resolve) =>
|
||||
requestAnimationFrame(() => requestAnimationFrame(resolve)),
|
||||
const result = await window.__qaOutlinePromise;
|
||||
let annotation = null;
|
||||
const deadline = performance.now() + 30_000;
|
||||
while (performance.now() < deadline) {
|
||||
annotation = (window.__gevAnnotations?.list?.() || []).find(
|
||||
(item) => item.label === label,
|
||||
);
|
||||
return {
|
||||
commandToRenderMs: performance.now() - window.__qaOutlineStarted,
|
||||
result,
|
||||
annotation: {
|
||||
pending: Boolean(annotation.pendingOutline),
|
||||
unavailable: Boolean(annotation.outlineUnavailable),
|
||||
synthesized: Boolean(annotation.synthesized),
|
||||
footprintKind: annotation.footprintKind || null,
|
||||
ringPoints: annotation.ring?.length || 0,
|
||||
parts: annotation.polygons?.length || (annotation.ring ? 1 : 0),
|
||||
},
|
||||
measures: performance.getEntriesByType('measure').map((entry) => ({
|
||||
name: entry.name,
|
||||
duration: entry.duration,
|
||||
startTime: entry.startTime,
|
||||
detail: entry.detail,
|
||||
})),
|
||||
longTasks: window.__qaOutlineLongTasks.slice(),
|
||||
};
|
||||
}, label);
|
||||
if (annotation && !annotation.pendingOutline) break;
|
||||
await new Promise((resolve) => setTimeout(resolve, 25));
|
||||
}
|
||||
if (!annotation || annotation.pendingOutline)
|
||||
throw new Error(`${label}: outline did not settle`);
|
||||
const { scene } = window.__godsEyeView.viewer;
|
||||
await new Promise((resolve) => {
|
||||
const timer = setTimeout(resolve, 1500);
|
||||
const remove = scene.postRender.addEventListener(() => {
|
||||
clearTimeout(timer);
|
||||
remove();
|
||||
resolve();
|
||||
});
|
||||
scene.requestRender();
|
||||
});
|
||||
await new Promise((resolve) =>
|
||||
requestAnimationFrame(() => requestAnimationFrame(resolve)),
|
||||
);
|
||||
return {
|
||||
commandToRenderMs: performance.now() - window.__qaOutlineStarted,
|
||||
result,
|
||||
annotation: {
|
||||
pending: Boolean(annotation.pendingOutline),
|
||||
unavailable: Boolean(annotation.outlineUnavailable),
|
||||
synthesized: Boolean(annotation.synthesized),
|
||||
footprintKind: annotation.footprintKind || null,
|
||||
ringPoints: annotation.ring?.length || 0,
|
||||
parts: annotation.polygons?.length || (annotation.ring ? 1 : 0),
|
||||
},
|
||||
measures: performance.getEntriesByType('measure').map((entry) => ({
|
||||
name: entry.name,
|
||||
duration: entry.duration,
|
||||
startTime: entry.startTime,
|
||||
detail: entry.detail,
|
||||
})),
|
||||
longTasks: window.__qaOutlineLongTasks.slice(),
|
||||
};
|
||||
}, label);
|
||||
}
|
||||
|
||||
async function driveOutline(page, label) {
|
||||
@@ -390,6 +477,7 @@ try {
|
||||
);
|
||||
assert.equal(trafficStats.error, null, 'overlap traffic source error');
|
||||
overlap.measures = relevantMeasures(overlap.measures);
|
||||
overlap.work = workEvidence(overlap.measures, 'overlap');
|
||||
overlap.network = network.filter(
|
||||
(entry) => entry.phase === 'overlap' && entry.targetTile,
|
||||
);
|
||||
@@ -422,12 +510,12 @@ try {
|
||||
report.overlap = {
|
||||
applicationFetches: overlapApplicationRequests,
|
||||
targetNetworkRequests: overlap.network.length,
|
||||
transferBytes: sum(
|
||||
overlap.network.map((entry) => entry.transferBytes),
|
||||
),
|
||||
transferBytes: sum(overlap.network.map((entry) => entry.transferBytes)),
|
||||
decodes: overlapDecodes.length,
|
||||
decodeMs: round(sum(overlapDecodes)),
|
||||
longTasks: overlap.longTasks.length,
|
||||
longTaskEntries: overlap.longTasks,
|
||||
work: overlap.work,
|
||||
};
|
||||
await page.close();
|
||||
continue;
|
||||
@@ -483,19 +571,20 @@ try {
|
||||
`sample ${run}: traffic did not load ${TARGET_PATH}`,
|
||||
);
|
||||
assert.equal(
|
||||
targetProjectionMeasures.length,
|
||||
2,
|
||||
`sample ${run}: traffic did not prepare the target outline projection`,
|
||||
);
|
||||
assert.ok(
|
||||
targetProjectionMs <= FRAME_BUDGET_MS,
|
||||
`sample ${run}: traffic-idle target projection ${targetProjectionMs} ms exceeds ${FRAME_BUDGET_MS} ms`,
|
||||
trafficMeasures.filter((entry) =>
|
||||
['outlines:street-extract', 'outlines:polygon-extract'].includes(
|
||||
entry.name,
|
||||
),
|
||||
).length,
|
||||
0,
|
||||
`sample ${run}: traffic must leave outline projection to the explicit ask`,
|
||||
);
|
||||
|
||||
phase = 'outline-cold';
|
||||
const cold = await driveOutline(page, `QA Capitol cold ${run}`);
|
||||
await sleep(750);
|
||||
cold.measures = relevantMeasures(cold.measures);
|
||||
cold.work = workEvidence(cold.measures, 'cold');
|
||||
cold.network = network.filter(
|
||||
(entry) => entry.phase === 'outline-cold' && entry.targetTile,
|
||||
);
|
||||
@@ -509,6 +598,7 @@ try {
|
||||
const warm = await driveOutline(page, `QA Capitol warm ${run}`);
|
||||
await sleep(750);
|
||||
warm.measures = relevantMeasures(warm.measures);
|
||||
warm.work = workEvidence(warm.measures, 'warm');
|
||||
warm.network = network.filter(
|
||||
(entry) => entry.phase === 'outline-warm' && entry.targetTile,
|
||||
);
|
||||
@@ -530,22 +620,54 @@ try {
|
||||
const coldDecodes = measures(cold.measures, 'roads:decode');
|
||||
const coldInstalls = measures(cold.measures, 'outlines:install');
|
||||
const warmDecodes = measures(warm.measures, 'roads:decode');
|
||||
const coldProjectionMeasures = cold.measures.filter(
|
||||
(entry) =>
|
||||
entry.detail?.tile === targetTile &&
|
||||
['outlines:street-extract', 'outlines:polygon-extract'].includes(
|
||||
entry.name,
|
||||
),
|
||||
);
|
||||
cold.targetProjectionMs = sum(
|
||||
coldProjectionMeasures.map((entry) => entry.ms),
|
||||
);
|
||||
assert.equal(
|
||||
cold.network.length,
|
||||
0,
|
||||
'shared decoded tile performs no second application fetch',
|
||||
);
|
||||
assert.equal(sum(cold.network.map((entry) => entry.transferBytes)), 0);
|
||||
assert.equal(coldDecodes.length, 0, 'shared decoded tile is not parsed again');
|
||||
assert.equal(
|
||||
measures(cold.measures, 'outlines:street-extract').length,
|
||||
coldDecodes.length,
|
||||
0,
|
||||
'traffic idle preparation owns street extraction',
|
||||
'shared decoded tile is not parsed again',
|
||||
);
|
||||
assert.equal(
|
||||
measures(cold.measures, 'outlines:polygon-extract').length,
|
||||
coldProjectionMeasures.filter(
|
||||
(entry) => entry.name === 'outlines:street-extract',
|
||||
).length,
|
||||
1,
|
||||
'the first explicit cold ask owns target street extraction exactly once',
|
||||
);
|
||||
assert.equal(
|
||||
coldProjectionMeasures.filter(
|
||||
(entry) => entry.name === 'outlines:polygon-extract',
|
||||
).length,
|
||||
1,
|
||||
'the first explicit cold ask owns target polygon extraction exactly once',
|
||||
);
|
||||
assert.ok(
|
||||
cold.targetProjectionMs <= FRAME_BUDGET_MS,
|
||||
`sample ${run}: cold target projection ${cold.targetProjectionMs} ms exceeds ${FRAME_BUDGET_MS} ms`,
|
||||
);
|
||||
assert.equal(
|
||||
measures(warm.measures, 'outlines:street-extract').length,
|
||||
0,
|
||||
'traffic idle preparation owns polygon extraction',
|
||||
'warm reuse performs no street extraction',
|
||||
);
|
||||
assert.equal(
|
||||
measures(warm.measures, 'outlines:polygon-extract').length,
|
||||
0,
|
||||
'warm reuse performs no polygon extraction',
|
||||
);
|
||||
assert.ok(coldInstalls.length >= 1, 'cold outline installs geometry');
|
||||
assert.equal(warm.network.length, 0, 'decoded-cache hit performs no fetch');
|
||||
@@ -593,7 +715,7 @@ try {
|
||||
sum(measures(cold.measures, 'outlines:polygon-extract')),
|
||||
),
|
||||
installMs: round(sum(coldInstalls)),
|
||||
mainThreadCpuMs: round(
|
||||
legacyInclusiveMs: round(
|
||||
sum(coldDecodes) +
|
||||
sum(measures(cold.measures, 'outlines:street-extract')) +
|
||||
sum(measures(cold.measures, 'outlines:polygon-extract')) +
|
||||
@@ -611,7 +733,9 @@ try {
|
||||
await page.close();
|
||||
}
|
||||
|
||||
const coldCpu = report.samples.map((sample) => sample.cold.mainThreadCpuMs);
|
||||
const coldInclusive = report.samples.map(
|
||||
(sample) => sample.cold.legacyInclusiveMs,
|
||||
);
|
||||
const outlineLongTasks = report.samples.flatMap((sample) => [
|
||||
...sample.cold.longTasks,
|
||||
...sample.warm.longTasks,
|
||||
@@ -623,9 +747,9 @@ try {
|
||||
samples: report.samples.length,
|
||||
overlapApplicationFetches: report.overlap?.applicationFetches ?? null,
|
||||
overlapDecodes: report.overlap?.decodes ?? null,
|
||||
coldCpuP50Ms: round(percentile(coldCpu, 0.5)),
|
||||
coldCpuP95Ms: round(percentile(coldCpu, 0.95)),
|
||||
coldCpuMaxMs: round(Math.max(...coldCpu)),
|
||||
legacyInclusiveP50Ms: round(percentile(coldInclusive, 0.5)),
|
||||
legacyInclusiveP95Ms: round(percentile(coldInclusive, 0.95)),
|
||||
legacyInclusiveMaxMs: round(Math.max(...coldInclusive)),
|
||||
coldCommandToRenderP95Ms: round(
|
||||
percentile(
|
||||
report.samples.map((sample) => sample.cold.commandToRenderMs),
|
||||
@@ -651,10 +775,8 @@ try {
|
||||
(sample) => measures(sample.warm.measures, 'roads:decode').length,
|
||||
),
|
||||
),
|
||||
trafficIdleProjectionMaxMs: round(
|
||||
Math.max(
|
||||
...report.samples.map((sample) => sample.traffic.targetProjectionMs),
|
||||
),
|
||||
coldProjectionMaxMs: Math.max(
|
||||
...report.samples.map((sample) => sample.cold.targetProjectionMs),
|
||||
),
|
||||
trafficBaselineLongTasks: trafficLongTasks.length,
|
||||
trafficBaselineMaxLongTaskMs: round(
|
||||
@@ -669,13 +791,29 @@ try {
|
||||
: 0,
|
||||
),
|
||||
};
|
||||
assert.ok(
|
||||
report.summary.coldCpuP95Ms <= FRAME_BUDGET_MS,
|
||||
`cold decode+extract+install p95 ${report.summary.coldCpuP95Ms} ms exceeds ${FRAME_BUDGET_MS} ms`,
|
||||
const coldSlices = report.samples.map(
|
||||
(sample) => sample.cold.work.maxSliceMs,
|
||||
);
|
||||
report.summary.coldOwnedSliceP95Ms = round(percentile(coldSlices, 0.95));
|
||||
report.summary.maxOwnedSliceMs = Math.max(
|
||||
report.overlap.work.maxSliceMs,
|
||||
...report.samples.flatMap((sample) => [
|
||||
sample.cold.work.maxSliceMs,
|
||||
sample.warm.work.maxSliceMs,
|
||||
]),
|
||||
);
|
||||
report.summary.maxSamplerCompletionMs = Math.max(
|
||||
report.overlap.work.completionMs,
|
||||
...report.samples.flatMap((sample) => [
|
||||
sample.cold.work.completionMs,
|
||||
sample.warm.work.completionMs,
|
||||
]),
|
||||
);
|
||||
assert.ok(report.summary.maxOwnedSliceMs <= FRAME_BUDGET_MS);
|
||||
assert.ok(report.summary.maxSamplerCompletionMs <= 2000);
|
||||
assert.ok(
|
||||
report.summary.trafficIdleProjectionMaxMs <= FRAME_BUDGET_MS,
|
||||
'traffic-idle outline projection exceeded one frame',
|
||||
report.summary.coldProjectionMaxMs <= FRAME_BUDGET_MS,
|
||||
'cold outline projection exceeded one frame',
|
||||
);
|
||||
assert.equal(report.summary.longTasks, 0, 'outline ask created a Long Task');
|
||||
assert.equal(report.summary.coldTransferBytes, 0);
|
||||
@@ -689,7 +827,7 @@ try {
|
||||
console.table(
|
||||
report.samples.map((sample) => ({
|
||||
run: sample.run,
|
||||
trafficPrepMs: sample.traffic.targetProjectionMs,
|
||||
coldProjectionMs: sample.cold.targetProjectionMs,
|
||||
appFetches: sample.cold.applicationFetches,
|
||||
transferBytes: sample.cold.transferBytes,
|
||||
bodyReadMs: sample.cold.bodyReadMs,
|
||||
@@ -697,7 +835,8 @@ try {
|
||||
streetMs: sample.cold.streetExtractMs,
|
||||
polygonMs: sample.cold.polygonExtractMs,
|
||||
installMs: sample.cold.installMs,
|
||||
cpuMs: sample.cold.mainThreadCpuMs,
|
||||
legacyInclusiveMs: sample.cold.legacyInclusiveMs,
|
||||
maxOwnedSliceMs: sample.cold.work.maxSliceMs,
|
||||
renderMs: round(sample.cold.commandToRenderMs),
|
||||
longTasks: sample.cold.longTasks.length,
|
||||
})),
|
||||
|
||||
Reference in new issue
Block a user