fix: bind performance evidence to production resources

This commit is contained in:
2026-09-02 08:53:00 +03:00
parent 5b7e47c2a2
commit e3ac3a4db4
23 changed files with 642 additions and 60 deletions

View File

@@ -1,3 +1,5 @@
import type { SceneGpuBudgetSnapshot } from '@/scene/resources';
declare const __PORTFOLIO_TEST_BUILD__: boolean;
declare const __PORTFOLIO_TEST_TOKEN_DIGEST__: string;
@@ -37,6 +39,7 @@ export interface ScriptedActionSample {
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.');
@@ -115,7 +118,7 @@ export const evaluateEventToNextPaint = (
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.');
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) };
@@ -192,6 +195,7 @@ interface PerformanceSnapshot {
cutoff: number;
navigationBarrier: { armed: boolean; pendingEpoch: number | null; cancelledEpoch: number | null };
actions: readonly ScriptedActionSample[];
runtimeAllocation: RuntimeAllocationSample | null;
}
interface PerformanceHooks {
@@ -200,6 +204,7 @@ interface PerformanceHooks {
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;
@@ -234,6 +239,7 @@ export const installAuthorizedPerformanceInstrumentation = async (): Promise<voi
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;
@@ -325,6 +331,13 @@ export const installAuthorizedPerformanceInstrumentation = async (): Promise<voi
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;
@@ -383,6 +396,7 @@ export const installAuthorizedPerformanceInstrumentation = async (): Promise<voi
...record,
eventEntries: Object.freeze([...record.eventEntries]),
}))),
runtimeAllocation,
}),
};
Object.defineProperty(window, '__PORTFOLIO_PERFORMANCE__', {