import type { SceneGpuBudgetSnapshot } from '@/scene/resources'; 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; captureEndTime: number | null; 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 type RuntimeAllocationSample = SceneGpuBudgetSnapshot; 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 && (action.captureEndTime === null || entry.startTime < action.captureEndTime) )); if (matching.length === 0) return 16; const groups = new Map(); 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 for ${action.id}: ${JSON.stringify(matching)}`); 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[]; runtimeAllocation: RuntimeAllocationSample | null; } interface PerformanceHooks { readonly version: 'drive-trace.v1'; startTrace(): void; endTrace(): void; recordSceneFrame(start: number, end: number): void; recordSceneState(state: string): void; recordRuntimeAllocation(allocation: RuntimeAllocationSample): 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 => { 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 => { 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 runtimeAllocation: RuntimeAllocationSample | 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(); 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 && timed.startTime >= record.dispatchTime && (record.captureEndTime === null || timed.startTime < record.captureEndTime)) { (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; } }, recordRuntimeAllocation(allocation) { runtimeAllocation = Object.freeze({ ...allocation, textures: Object.freeze(allocation.textures.map((item) => Object.freeze({ ...item }))), renderTargets: Object.freeze(allocation.renderTargets.map((item) => Object.freeze({ ...item }))), }); }, 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.'); const dispatchTime = performance.now(); for (const record of actionRecords.values()) { if (record.element === element && record.captureEndTime === null) record.captureEndTime = dispatchTime; } actionRecords.set(id, { id, target: id, dispatchTime, captureEndTime: null, 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]), }))), runtimeAllocation, }), }; Object.defineProperty(window, '__PORTFOLIO_PERFORMANCE__', { configurable: false, enumerable: false, writable: false, value: Object.freeze(hooks), }); };