Files
ontime/apps/client/src/common/devtools/cuesheet-metrics/usePerfMark.ts
T
Claude eab63e838d perf(cuesheet): add temporary first-render metrics scaffold
Adds a dev-only, self-contained instrumentation module under
common/devtools/cuesheet-metrics to measure the first-render (mount) cost
of virtualised cuesheet rows, so scroll-performance changes can be backed
by before/after numbers.

- Console-only API on window.__cuesheetPerf (deterministic scroll benchmark
  + manual start/stop), gated by isDev && ?perf=1, runtime-inert in prod.
- Whole-row mount probe plus per-subsystem attribution: colour calc,
  getVisibleCells, AutoTextarea autosize, Tooltip portal mount,
  useReactiveTextInput hotkey-handler init; FPS/long-frame timing.
- All edits to existing files tagged // PERF-METRICS for a one-pass teardown.

Temporary: to be deleted once the optimizations are proven.
2026-06-15 20:17:01 +00:00

39 lines
1.4 KiB
TypeScript

/**
* PERF-METRICS — temporary cuesheet scroll-performance scaffold (delete with this directory).
*
* Lightweight timing helpers. All no-op when instrumentation is disabled so the call sites in
* shared components stay cheap (and fold away in production builds).
*/
import { useLayoutEffect, useRef } from 'react';
import { PERF_ENABLED } from './perfConfig';
import { recordMark, recordRowMount } from './perfStore';
/** Times the synchronous `fn`, records the duration under `name`, and returns its result. */
export function timeSync<T>(name: string, fn: () => T): T {
if (!PERF_ENABLED) return fn();
const start = performance.now();
try {
return fn();
} finally {
recordMark(name, performance.now() - start);
}
}
/**
* Measures the mount cost of a component (render-start → post-commit layout) and records it
* under `${name}.mount`. Used on EventRow and on the Tooltip subtree to attribute per-row
* first-render cost. Pass `countAsRow` on the row probe so only rows feed the rows-mounted tally.
*/
export function useMountProbe(name: string, countAsRow = false): void {
const renderStart = useRef(PERF_ENABLED ? performance.now() : 0);
useLayoutEffect(() => {
if (!PERF_ENABLED) return;
recordMark(`${name}.mount`, performance.now() - renderStart.current);
if (countAsRow) {
recordRowMount();
}
// eslint-disable-next-line react-hooks/exhaustive-deps -- mount-only probe
}, []);
}