perf(runtime): cache the derived runtime key

`getRuntimeKey` keys caches, stores, and persisted state across the whole UI,
so it runs on store reads, event handling, and render paths. Until the runtime
endpoint is explicitly initialised, every call re-derived the key by trimming
two injected globals and constructing three URL objects.

In a streaming capture this made `readInjectedLocalOrigin` the single most
expensive application function: 315 ms of self time, 12% of all main-thread
busy time. After the change it does not appear in the profile at all, and the
same capture went from two long tasks to none, with the longest task dropping
from 210 ms to 47 ms.

The key depends only on the active API base URL and two injected globals, and
`switchRuntimeEndpoint` writes the injected API base URL at runtime, so the
cache is validated against the raw untrimmed values rather than memoised
outright. That comparison allocates nothing and still recomputes as soon as any
input changes. Tests cover both directions, including an operation-count
assertion that repeated calls construct no URLs.

The streaming profiler also reports output-normalised metrics, because response
length varies between runs and makes per-second totals incomparable.
This commit is contained in:
Bohdan Triapitsyn
2026-08-03 15:31:22 +03:00
parent 0d603649dc
commit 107fe45248
3 changed files with 139 additions and 3 deletions
@@ -0,0 +1,80 @@
import { afterEach, beforeEach, describe, expect, test } from 'bun:test';
import { getRuntimeKey } from './runtime-switch';
/**
* `getRuntimeKey` runs on store, event, and render paths, so its cost is
* multiplied by everything the UI does. These tests pin both directions of the
* derived-key cache: repeated calls with unchanged inputs must do no work, and
* any change to the inputs it derives from must still be observed.
*
* This lives in its own file because the cache is only reachable while the
* runtime endpoint has not been explicitly initialised, and module state is
* shared across tests within a file.
*/
type RuntimeWindow = typeof globalThis & {
__OPENCHAMBER_API_BASE_URL__?: string;
__OPENCHAMBER_LOCAL_ORIGIN__?: string;
};
const previousWindow = Object.getOwnPropertyDescriptor(globalThis, 'window');
const NativeURL = globalThis.URL;
let urlConstructions = 0;
const setRuntimeWindow = (apiBaseUrl: string | undefined, localOrigin: string | undefined): void => {
const runtimeWindow = {} as RuntimeWindow;
if (apiBaseUrl !== undefined) runtimeWindow.__OPENCHAMBER_API_BASE_URL__ = apiBaseUrl;
if (localOrigin !== undefined) runtimeWindow.__OPENCHAMBER_LOCAL_ORIGIN__ = localOrigin;
Object.defineProperty(globalThis, 'window', { value: runtimeWindow, configurable: true, writable: true });
};
beforeEach(() => {
urlConstructions = 0;
class CountingURL extends NativeURL {
constructor(url: string | URL, base?: string | URL) {
urlConstructions += 1;
super(url, base);
}
}
globalThis.URL = CountingURL as unknown as typeof URL;
});
afterEach(() => {
globalThis.URL = NativeURL;
if (previousWindow) Object.defineProperty(globalThis, 'window', previousWindow);
else Reflect.deleteProperty(globalThis, 'window');
});
describe('getRuntimeKey caching', () => {
test('resolves a same-origin endpoint to the local runtime key', () => {
setRuntimeWindow('https://app.example.com/api', 'https://app.example.com');
expect(getRuntimeKey()).toBe('local');
});
test('performs no URL work on repeated calls with unchanged inputs', () => {
setRuntimeWindow('https://remote.example.com', 'https://app.example.com');
const first = getRuntimeKey();
expect(first).toBe('url:https://remote.example.com');
urlConstructions = 0;
for (let index = 0; index < 50; index += 1) expect(getRuntimeKey()).toBe(first);
expect(urlConstructions).toBe(0);
});
test('recomputes when the injected API base URL changes at runtime', () => {
setRuntimeWindow('https://first.example.com', 'https://app.example.com');
expect(getRuntimeKey()).toBe('url:https://first.example.com');
(globalThis as RuntimeWindow & { window: RuntimeWindow }).window.__OPENCHAMBER_API_BASE_URL__ = 'https://second.example.com';
expect(getRuntimeKey()).toBe('url:https://second.example.com');
});
test('recomputes when the injected local origin changes at runtime', () => {
setRuntimeWindow('https://app.example.com', 'https://other.example.com');
expect(getRuntimeKey()).toBe('url:https://app.example.com');
(globalThis as RuntimeWindow & { window: RuntimeWindow }).window.__OPENCHAMBER_LOCAL_ORIGIN__ = 'https://app.example.com';
expect(getRuntimeKey()).toBe('local');
});
});
+43 -2
View File
@@ -76,11 +76,52 @@ const sameOrigin = (left: string, right: string): boolean => {
};
export const getRuntimeApiBaseUrl = (): string => activeApiBaseUrl || readInjectedApiBaseUrl();
// `getRuntimeKey` keys caches, stores, and persisted state across the whole UI,
// so it runs on store reads, event handling, and render paths. Before the
// runtime endpoint is explicitly initialised, every call re-derived the key by
// trimming two injected globals and constructing three `URL` objects, which
// made this one of the most expensive functions during streaming.
//
// The result depends only on `activeApiBaseUrl` and the two injected globals,
// and `switchRuntimeEndpoint` writes the injected API base URL at runtime, so
// the cache is validated against the raw, untrimmed values. That comparison
// allocates nothing and still recomputes the moment any input changes.
let cachedRuntimeKey = '';
let cachedActiveApiBaseUrl: string | null = null;
let cachedRawApiBaseUrl: string | undefined;
let cachedRawLocalOrigin: string | undefined;
const readRawRuntimeGlobal = (key: '__OPENCHAMBER_API_BASE_URL__' | '__OPENCHAMBER_LOCAL_ORIGIN__'): string | undefined => {
if (typeof window === 'undefined') return undefined;
const value = (window as typeof window & {
__OPENCHAMBER_API_BASE_URL__?: string;
__OPENCHAMBER_LOCAL_ORIGIN__?: string;
})[key];
return typeof value === 'string' ? value : undefined;
};
export const getRuntimeKey = (): string => {
if (activeRuntimeKey) return activeRuntimeKey;
const rawApiBaseUrl = readRawRuntimeGlobal('__OPENCHAMBER_API_BASE_URL__');
const rawLocalOrigin = readRawRuntimeGlobal('__OPENCHAMBER_LOCAL_ORIGIN__');
if (
cachedActiveApiBaseUrl === activeApiBaseUrl
&& cachedRawApiBaseUrl === rawApiBaseUrl
&& cachedRawLocalOrigin === rawLocalOrigin
) {
return cachedRuntimeKey;
}
const apiBaseUrl = getRuntimeApiBaseUrl();
if (sameOrigin(apiBaseUrl, readInjectedLocalOrigin())) return 'local';
return normalizeRuntimeUrlKey(apiBaseUrl);
cachedRuntimeKey = sameOrigin(apiBaseUrl, readInjectedLocalOrigin())
? 'local'
: normalizeRuntimeUrlKey(apiBaseUrl);
cachedActiveApiBaseUrl = activeApiBaseUrl;
cachedRawApiBaseUrl = rawApiBaseUrl;
cachedRawLocalOrigin = rawLocalOrigin;
return cachedRuntimeKey;
};
export const initializeRuntimeEndpoint = (options: { apiBaseUrl?: string | null; runtimeKey?: string | null } = {}): void => {
+16 -1
View File
@@ -187,6 +187,9 @@ const REPORTED_METRICS = [
{ key: "layoutsPerSecond", label: "Layouts/sec", unit: "", lowerIsBetter: true },
{ key: "framesPerSecond", label: "Animation frames/sec", unit: "", lowerIsBetter: false },
{ key: "streamSeconds", label: "Stream duration", unit: "s", lowerIsBetter: true },
{ key: "renderedCharacters", label: "Rendered characters", unit: "", lowerIsBetter: false },
{ key: "busyMsPerKilochar", label: "Busy per 1k chars", unit: "ms", lowerIsBetter: true },
{ key: "recalcStylePerKilochar", label: "Style recalcs per 1k", unit: "", lowerIsBetter: true },
{ key: "nodeGrowth", label: "DOM node growth", unit: "", lowerIsBetter: true },
{ key: "listenerGrowth", label: "Listener growth", unit: "", lowerIsBetter: true },
{ key: "heapGrowthMbPerSecond", label: "Heap growth", unit: "MB/s", lowerIsBetter: true },
@@ -429,6 +432,8 @@ const main = async () => {
.some((entry) => entry.metric.startsWith("ui.message_list") && entry.count > 0)
const renderedStream = renderedAfter.messages > renderedBefore.messages && messageListRendered
const renderedCharacterGrowth = renderedAfter.characters - renderedBefore.characters
const tasks = summarizeLongTasks(traceEvents)
const delta = (name) => Number(after[name] ?? 0) - Number(before[name] ?? 0)
const perSecond = (name) => round(delta(name) / elapsedSeconds)
@@ -448,7 +453,7 @@ const main = async () => {
renderedStream,
renderedMessagesBefore: renderedBefore.messages,
renderedMessagesAfter: renderedAfter.messages,
renderedCharacterGrowth: renderedAfter.characters - renderedBefore.characters,
renderedCharacterGrowth,
traceComplete,
disposableSession: !options.keepSession && !options.session,
metrics: {
@@ -458,6 +463,16 @@ const main = async () => {
recalcStylePerSecond: perSecond("RecalcStyleCount"),
layoutsPerSecond: perSecond("LayoutCount"),
framesPerSecond: round(Number(probe?.counters?.rafScheduled ?? 0) / elapsedSeconds),
// Response length varies between runs even for an identical prompt, so
// per-second and total figures are not comparable across captures.
// Normalising by rendered output is what makes two runs contrastable.
renderedCharacters: renderedCharacterGrowth,
busyMsPerKilochar: renderedCharacterGrowth > 0
? round((delta("TaskDuration") * 1000) / (renderedCharacterGrowth / 1000))
: 0,
recalcStylePerKilochar: renderedCharacterGrowth > 0
? round(delta("RecalcStyleCount") / (renderedCharacterGrowth / 1000))
: 0,
streamSeconds,
recordedSeconds: round(elapsedSeconds),
nodeStart: Number(before.Nodes ?? 0),