import { useMemo, useRef } from 'react'; import { isPerfLivePollWaitingForCpu, usePerfLiveSnapshot } from '../../../utils/perf/perfLiveStore'; import { usePerfLiveIncludeThreadGroups } from '../../../utils/perf/perfLivePollSettings'; import { togglePerfLiveOverlayPin, togglePipelineOverlayPin, usePerfLiveOverlayPins, usePipelineOverlayPinned, type PerfLiveOverlayPinId, } from '../../../utils/perf/perfOverlayPins'; import PerfProbeMetricCard, { PerfProbeMetricSection } from './PerfProbeMetricCard'; import PerfOverlayAppearanceControls from './PerfOverlayAppearanceControls'; import PerfOverlayModeControls from './PerfOverlayModeControls'; import PerfLivePollControls from './PerfLivePollControls'; function memoryBarPct(rssKb: number, maxKb: number): number { if (maxKb <= 0) return 0; return (rssKb / maxKb) * 100; } export default function SidebarPerfProbeMonitorTab() { const live = usePerfLiveSnapshot(); const livePins = usePerfLiveOverlayPins(); const fpsPinned = usePipelineOverlayPinned('pipeline:fps'); const analysisPinned = usePipelineOverlayPinned('pipeline:analysis'); const coverPinned = usePipelineOverlayPinned('pipeline:cover'); const cpu = live.cpu; const cpuSupported = cpu?.supported === true; const collecting = isPerfLivePollWaitingForCpu(); const includeThreadGroups = usePerfLiveIncludeThreadGroups(); const peakMemoryKbRef = useRef(1); const peakThreadCpuRef = useRef(1); const maxMemoryKb = useMemo(() => { const current = Math.max(1, ...(cpu?.memory.map(m => m.rss_kb) ?? [1])); // React Compiler refs rule: ref read imperatively outside reactive rendering; not used to compute the render output. // eslint-disable-next-line react-hooks/refs if (current > peakMemoryKbRef.current) peakMemoryKbRef.current = current; return peakMemoryKbRef.current; }, [cpu?.memory]); // React Compiler refs rule: ref read imperatively outside reactive rendering; not used to compute the render output. // eslint-disable-next-line react-hooks/refs const maxThreadCpu = useMemo(() => { const current = Math.max(1, ...(cpu?.threadCpu.map(t => t.pct) ?? [1])); if (current > peakThreadCpuRef.current) peakThreadCpuRef.current = current; return peakThreadCpuRef.current; }, [cpu?.threadCpu]); if (collecting) { return (
Collecting live samples…
); } const toggleLive = (id: PerfLiveOverlayPinId) => () => togglePerfLiveOverlayPin(id); const livePinned = (id: PerfLiveOverlayPinId) => livePins.has(id); return (
togglePipelineOverlayPin('pipeline:fps')} /> togglePipelineOverlayPin('pipeline:analysis')} /> togglePipelineOverlayPin('pipeline:cover')} /> {cpu && !cpuSupported && (
Live CPU and RSS sampling is unavailable on this platform. Pipeline, UI rate, and analysis metrics below still work.
)} {cpuSupported && cpu && ( <> {includeThreadGroups && ( {/* React Compiler refs rule: the row renderer reads pin-state refs (live overlay); intentional, not reactive render data. */} {/* eslint-disable-next-line react-hooks/refs */} {cpu.threadCpu.length > 0 ? cpu.threadCpu.map(row => { const pinId = `cpu:thread:${row.label}` as PerfLiveOverlayPinId; return ( 1 ? `${row.threadCount} threads` : undefined} barPct={(row.pct / maxThreadCpu) * 100} barTone="cpu" pinned={livePinned(pinId)} onTogglePin={toggleLive(pinId)} /> ); }) : (
No named psysonic threads yet — wait for the next poll or load audio/analysis work.
)}
)} {cpu.memory.length > 0 && ( {/* React Compiler refs rule: the row renderer reads pin-state refs (live overlay); intentional, not reactive render data. */} {/* eslint-disable-next-line react-hooks/refs */} {cpu.memory.map(row => { const pinId = `mem:${row.label}` as PerfLiveOverlayPinId; return ( ); })} )} )} {live.diagRates && ( )} {live.analysis && ( {live.analysis.lastTotalMs != null && ( )} )} {live.cover && ( 0 ? `${live.cover.done.toLocaleString()} / ${live.cover.total.toLocaleString()} cached` : 'covers cached per minute'} pinned={livePinned('cover:cpm')} onTogglePin={toggleLive('cover:cpm')} /> )}
); }