Feat/performance probe fps overlay (#472)

* feat(perf-probe): add FPS overlay toggle and tidy probe modal

Add optional rAF-based FPS readout controlled by a persisted probe flag.
Remove the separate keyboard shortcut. Collapse all phase sections by default.

* perf(fps-overlay): subscribe only to showFpsOverlay flag

Add usePerfProbeFlag so the overlay does not re-render when other probe
toggles change. Track the animation frame id with a loop-local variable.
This commit is contained in:
cucadmuh
2026-05-06 02:13:59 +03:00
committed by GitHub
parent c3d37546cf
commit de3c0d9da1
5 changed files with 100 additions and 5 deletions
+48
View File
@@ -0,0 +1,48 @@
import { useEffect, useState } from 'react';
import { createPortal } from 'react-dom';
import { usePerfProbeFlag } from '../utils/perfFlags';
const SAMPLE_MS = 500;
/** FPS from rAF callbacks over sliding ~500ms windows; only runs when Performance Probe enables the overlay. */
export default function FpsOverlay() {
const showFpsOverlay = usePerfProbeFlag('showFpsOverlay');
const [fps, setFps] = useState(0);
useEffect(() => {
if (!showFpsOverlay) {
setFps(0);
return;
}
let frames = 0;
let lastReport = performance.now();
let rafId = 0;
const loop = () => {
frames++;
const now = performance.now();
if (now - lastReport >= SAMPLE_MS) {
const elapsedSec = (now - lastReport) / 1000;
setFps(Math.round(frames / elapsedSec));
frames = 0;
lastReport = now;
}
rafId = requestAnimationFrame(loop);
};
rafId = requestAnimationFrame(loop);
return () => cancelAnimationFrame(rafId);
}, [showFpsOverlay]);
if (!showFpsOverlay) return null;
return createPortal(
<div className="fps-overlay" aria-hidden="true">
{fps}
{' '}
<span className="fps-overlay__unit">FPS</span>
</div>,
document.body,
);
}