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'; import PerfCoverThreadsControl from './PerfCoverThreadsControl'; 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])); if (current > peakMemoryKbRef.current) peakMemoryKbRef.current = current; return peakMemoryKbRef.current; }, [cpu?.memory]); 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 && ( {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 && ( {cpu.memory.map(row => { const pinId = `mem:${row.label}` as PerfLiveOverlayPinId; return ( ); })} )} )} {live.diagRates && ( )} {live.analysis && ( {live.analysis.lastTotalMs != null && ( )} )}
); }