perf: enforce journey budgets and reference traces

This commit is contained in:
2026-09-02 07:48:02 +03:00
parent 8089d061ec
commit f4cf9fc77e
25 changed files with 1432 additions and 23 deletions

View File

@@ -0,0 +1,394 @@
declare const __PORTFOLIO_TEST_BUILD__: boolean;
declare const __PORTFOLIO_TEST_TOKEN_DIGEST__: string;
const TEST_BUILD = typeof __PORTFOLIO_TEST_BUILD__ !== 'undefined' && __PORTFOLIO_TEST_BUILD__;
const TEST_TOKEN_DIGEST = typeof __PORTFOLIO_TEST_TOKEN_DIGEST__ === 'undefined'
? ''
: __PORTFOLIO_TEST_TOKEN_DIGEST__;
export interface LayoutShiftSample {
startTime: number;
value: number;
hadRecentInput: boolean;
}
export interface LongTaskSample {
startTime: number;
duration: number;
}
export interface EventTimingSample {
target: string;
startTime: number;
duration: number;
interactionId: number;
}
export interface ScriptedActionSample {
id: string;
target: string;
dispatchTime: number;
acknowledgementCount: number;
mutationTime: number | null;
doubleRafTime: number | null;
eventTimingSupported: boolean;
eventEntries: readonly EventTimingSample[];
}
export interface SceneInterval { start: number; end: number }
export interface SceneFrameSample { start: number; end: number }
export const nearestRankP95 = (samples: readonly number[]): number => {
if (samples.length === 0) throw new Error('At least one sample is required.');
const sorted = [...samples].sort((left, right) => left - right);
return sorted[Math.ceil(0.95 * sorted.length) - 1]!;
};
export const latestLcpBeforeCutoff = (entries: readonly number[], cutoff: number): number => {
const eligible = entries.filter((entry) => entry < cutoff);
if (eligible.length === 0) throw new Error('An LCP entry is required before the cutoff.');
return Math.max(...eligible);
};
export const calculateCls = (entries: readonly LayoutShiftSample[]): number => {
const eligible = entries
.filter((entry) => !entry.hadRecentInput)
.sort((left, right) => left.startTime - right.startTime);
let maximum = 0;
let windowStart = -Infinity;
let previous = -Infinity;
let sum = 0;
for (const entry of eligible) {
if (entry.startTime - previous > 1_000 || entry.startTime - windowStart > 5_000) {
windowStart = entry.startTime;
sum = 0;
}
sum += entry.value;
previous = entry.startTime;
maximum = Math.max(maximum, sum);
}
return maximum;
};
export const calculateLabTbt = (
tasks: readonly LongTaskSample[],
fcp: number | null,
runningAt: number,
): number => {
if (fcp === null) throw new Error('FCP is required for lab total blocking time.');
return tasks.reduce((total, task) => {
const start = Math.max(task.startTime + 50, fcp);
const end = Math.min(task.startTime + task.duration, runningAt);
return total + Math.max(0, end - start);
}, 0);
};
export const postRunningLongTasks = (
tasks: readonly LongTaskSample[],
runningAt: number,
traceEnd: number,
): LongTaskSample[] => tasks.filter((task) => (
task.startTime < traceEnd && task.startTime + task.duration > runningAt
));
const exactActionIds = new Set(['start', 'volume', 'mute', 'unmute', 'pause', 'resume', 'toolkit', 'contact']);
export const evaluateEventToNextPaint = (
actions: readonly ScriptedActionSample[],
): { values: number[]; p95: number } => {
if (actions.length !== 8 || new Set(actions.map((action) => action.id)).size !== 8 || actions.some((action) => !exactActionIds.has(action.id))) {
throw new Error('The exact eight scripted actions are required.');
}
const values = actions.map((action) => {
if (action.acknowledgementCount !== 1) throw new Error('Each action requires exactly one acknowledgement.');
if (action.mutationTime === null || action.mutationTime > action.dispatchTime + 500) throw new Error('The exact state mutation missed its deadline.');
if (action.doubleRafTime === null || action.doubleRafTime > action.dispatchTime + 500) throw new Error('Double RAF confirmation missed its deadline.');
if (!action.eventTimingSupported) throw new Error('Event Timing observation is unsupported.');
const matching = action.eventEntries.filter((entry) => (
entry.target === action.target
&& entry.startTime >= action.dispatchTime
&& entry.startTime <= action.dispatchTime + 500
));
if (matching.length === 0) return 16;
const groups = new Map<number, number>();
for (const entry of matching) {
if (entry.interactionId === 0) continue;
groups.set(entry.interactionId, Math.max(groups.get(entry.interactionId) ?? 0, entry.duration));
}
if (groups.size !== 1) throw new Error('Event Timing groups are ambiguous.');
return [...groups.values()][0]!;
});
return { values, p95: nearestRankP95(values) };
};
export const evaluateSceneContinuity = (
intervals: readonly SceneInterval[],
callbacks: readonly SceneFrameSample[],
expectedFramePeriod: number,
): { passes: boolean; expectedCallbacks: number; actualCallbacks: number } => {
if (!(expectedFramePeriod > 0)) throw new Error('Expected frame period must be positive.');
const eligible = intervals.filter((interval) => interval.end - interval.start >= expectedFramePeriod);
let expectedCallbacks = 0;
let actualCallbacks = 0;
let boundariesPass = eligible.length > 0;
for (const interval of eligible) {
expectedCallbacks += Math.floor((interval.end - interval.start) / expectedFramePeriod);
const inside = callbacks.filter((sample) => sample.start >= interval.start && sample.end <= interval.end);
actualCallbacks += inside.length;
if (inside.length === 0) {
boundariesPass = false;
continue;
}
if (inside[0]!.start - interval.start > 3 * expectedFramePeriod) boundariesPass = false;
for (let index = 1; index < inside.length; index += 1) {
if (inside[index]!.start - inside[index - 1]!.start > 3 * expectedFramePeriod) boundariesPass = false;
}
if (interval.end - inside.at(-1)!.end > 3 * expectedFramePeriod) boundariesPass = false;
}
const coverage = expectedCallbacks > 0 ? actualCallbacks / expectedCallbacks : 0;
return { passes: boundariesPass && coverage >= 0.9, expectedCallbacks, actualCallbacks };
};
export const calculateLostPresentationShare = (
rafTimestamps: readonly number[],
expectedFramePeriod: number,
minimumOpportunities: number,
): { opportunities: number; lost: number; share: number; hasSufficientCoverage: boolean } => {
let opportunities = 0;
let lost = 0;
for (let index = 1; index < rafTimestamps.length; index += 1) {
const interval = rafTimestamps[index]! - rafTimestamps[index - 1]!;
const nextOpportunities = Math.max(1, Math.round(interval / expectedFramePeriod));
opportunities += nextOpportunities;
lost += nextOpportunities - 1;
}
return {
opportunities,
lost,
share: opportunities === 0 ? 1 : lost / opportunities,
hasSufficientCoverage: opportunities >= minimumOpportunities,
};
};
export const unexpectedLateShifts = (
entries: readonly LayoutShiftSample[],
firstSceneFrame: number,
traceEnd: number,
): LayoutShiftSample[] => entries.filter((entry) => (
!entry.hadRecentInput && entry.startTime >= firstSceneFrame && entry.startTime < traceEnd
));
interface PerformanceSnapshot {
version: 'drive-trace.v1';
lcp: readonly number[];
layoutShifts: readonly LayoutShiftSample[];
longTasks: readonly LongTaskSample[];
pageRafs: readonly number[];
sceneFrames: readonly SceneFrameSample[];
sceneIntervals: readonly SceneInterval[];
firstSceneFrame: number | null;
traceStart: number | null;
traceEnd: number | null;
cutoff: number;
navigationBarrier: { armed: boolean; pendingEpoch: number | null; cancelledEpoch: number | null };
actions: readonly ScriptedActionSample[];
}
interface PerformanceHooks {
readonly version: 'drive-trace.v1';
startTrace(): void;
endTrace(): void;
recordSceneFrame(start: number, end: number): void;
recordSceneState(state: string): void;
armNavigationSettlementBarrier(): void;
registerNavigationSettlement(epoch: number): void;
holdNavigationSettlement(epoch: number): boolean;
noteNavigationEpoch(epoch: number): void;
beginAction(id: string, selector: string): void;
recordActionMutation(id: string): void;
snapshot(): PerformanceSnapshot;
}
declare global {
interface Window {
__PORTFOLIO_PERFORMANCE__?: PerformanceHooks;
}
}
const digest = async (value: string): Promise<string> => {
const output = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(value));
return [...new Uint8Array(output)].map((byte) => byte.toString(16).padStart(2, '0')).join('');
};
export const installAuthorizedPerformanceInstrumentation = async (): Promise<void> => {
if (!TEST_BUILD) return;
const url = new URL(location.href);
if (url.searchParams.get('__portfolio_performance') !== 'drive-trace.v1') return;
const token = url.searchParams.get('__portfolio_test_token');
if (token === null || await digest(token) !== TEST_TOKEN_DIGEST) return;
const lcp: number[] = [];
const layoutShifts: LayoutShiftSample[] = [];
const longTasks: LongTaskSample[] = [];
const pageRafs: number[] = [];
const sceneFrames: SceneFrameSample[] = [];
const sceneIntervals: SceneInterval[] = [];
let firstSceneFrame: number | null = null;
let traceStart: number | null = null;
let traceEnd: number | null = null;
let runningIntervalStart: number | null = null;
let cutoff = Infinity;
let sentinel = 0;
let barrierArmed = false;
let barrierPendingEpoch: number | null = null;
let barrierCancelledEpoch: number | null = null;
const actionRecords = new Map<string, ScriptedActionSample & { element: Element | null }>();
const observe = (type: string, callback: (entry: PerformanceEntry) => void): void => {
if (typeof PerformanceObserver === 'undefined') return;
try {
const observer = new PerformanceObserver((list) => list.getEntries().forEach(callback));
observer.observe({ type, buffered: true });
} catch { /* unsupported entry type */ }
};
observe('largest-contentful-paint', (entry) => lcp.push(entry.startTime));
observe('layout-shift', (entry) => {
const shift = entry as PerformanceEntry & { value?: number; hadRecentInput?: boolean };
layoutShifts.push({ startTime: shift.startTime, value: shift.value ?? 0, hadRecentInput: shift.hadRecentInput ?? false });
});
observe('longtask', (entry) => longTasks.push({ startTime: entry.startTime, duration: entry.duration }));
let eventTimingSupported = false;
if (typeof PerformanceObserver !== 'undefined') {
try {
const eventObserver = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
const timed = entry as PerformanceEntry & { interactionId?: number; target?: Node | null };
for (const record of actionRecords.values()) {
if (timed.target === record.element) {
(record.eventEntries as EventTimingSample[]).push({
target: record.id,
startTime: timed.startTime,
duration: timed.duration,
interactionId: timed.interactionId ?? 0,
});
}
}
}
});
const eventOptions = { type: 'event', buffered: true, durationThreshold: 16 } as PerformanceObserverInit & { durationThreshold: number };
eventObserver.observe(eventOptions);
eventTimingSupported = true;
} catch { /* Event Timing unsupported */ }
}
const cutOff = (event: Event): void => {
if (event.isTrusted) cutoff = Math.min(cutoff, performance.now());
};
addEventListener('pointerdown', cutOff, { capture: true, once: true });
addEventListener('keydown', cutOff, { capture: true, once: true });
document.addEventListener('visibilitychange', () => {
if (document.hidden) cutoff = Math.min(cutoff, performance.now());
});
const sentinelFrame = (now: number): void => {
if (traceStart !== null && traceEnd === null) pageRafs.push(now);
sentinel = requestAnimationFrame(sentinelFrame);
};
sentinel = requestAnimationFrame(sentinelFrame);
const hooks: PerformanceHooks = {
version: 'drive-trace.v1',
startTrace() {
traceStart = performance.now();
traceEnd = null;
pageRafs.length = 0;
sceneFrames.length = 0;
sceneIntervals.length = 0;
runningIntervalStart = document.querySelector('.journey-world')?.getAttribute('data-scene-state') === 'running' ? traceStart : null;
},
endTrace() {
traceEnd = performance.now();
if (runningIntervalStart !== null) {
sceneIntervals.push({ start: runningIntervalStart, end: traceEnd });
runningIntervalStart = null;
}
cancelAnimationFrame(sentinel);
},
recordSceneFrame(start, end) {
if (firstSceneFrame === null) firstSceneFrame = end;
if (traceStart !== null && traceEnd === null) sceneFrames.push({ start, end });
},
recordSceneState(state) {
const now = performance.now();
if (traceStart === null || traceEnd !== null) return;
if (state === 'running' && runningIntervalStart === null) runningIntervalStart = now;
if (state !== 'running' && runningIntervalStart !== null) {
sceneIntervals.push({ start: runningIntervalStart, end: now });
runningIntervalStart = null;
}
},
armNavigationSettlementBarrier() {
barrierArmed = true;
barrierPendingEpoch = null;
barrierCancelledEpoch = null;
},
registerNavigationSettlement(epoch) {
if (barrierArmed) barrierPendingEpoch = epoch;
},
holdNavigationSettlement(epoch) {
return barrierArmed && barrierPendingEpoch === epoch;
},
noteNavigationEpoch(epoch) {
if (barrierArmed && barrierPendingEpoch !== null && barrierPendingEpoch !== epoch) {
barrierCancelledEpoch = barrierPendingEpoch;
barrierPendingEpoch = null;
barrierArmed = false;
}
},
beginAction(id, selector) {
if (!exactActionIds.has(id) || actionRecords.has(id)) throw new Error('The performance action is invalid or duplicated.');
const element = document.querySelector(selector);
if (!(element instanceof Element)) throw new Error('The performance action target is unavailable.');
actionRecords.set(id, {
id,
target: id,
dispatchTime: performance.now(),
acknowledgementCount: 0,
mutationTime: null,
doubleRafTime: null,
eventTimingSupported,
eventEntries: [],
element,
});
},
recordActionMutation(id) {
const record = actionRecords.get(id);
if (record === undefined) return;
record.acknowledgementCount += 1;
record.mutationTime = performance.now();
requestAnimationFrame(() => requestAnimationFrame(() => { record.doubleRafTime = performance.now(); }));
},
snapshot: () => Object.freeze({
version: 'drive-trace.v1' as const,
lcp: Object.freeze([...lcp]),
layoutShifts: Object.freeze([...layoutShifts]),
longTasks: Object.freeze([...longTasks]),
pageRafs: Object.freeze([...pageRafs]),
sceneFrames: Object.freeze([...sceneFrames]),
sceneIntervals: Object.freeze([...sceneIntervals]),
firstSceneFrame,
traceStart,
traceEnd,
cutoff,
navigationBarrier: Object.freeze({ armed: barrierArmed, pendingEpoch: barrierPendingEpoch, cancelledEpoch: barrierCancelledEpoch }),
actions: Object.freeze([...actionRecords.values()].map(({ element: _element, ...record }) => Object.freeze({
...record,
eventEntries: Object.freeze([...record.eventEntries]),
}))),
}),
};
Object.defineProperty(window, '__PORTFOLIO_PERFORMANCE__', {
configurable: false,
enumerable: false,
writable: false,
value: Object.freeze(hooks),
});
};