fix(perf): keep probe monitor metrics visible on Windows (#933)

Stop replacing the whole Monitor tab when CPU/RSS sampling is unsupported;
show pipeline, UI rate, and analysis sections with an inline platform note.
Also compute UI diagRates when the Rust snapshot returns supported: false.
This commit is contained in:
cucadmuh
2026-05-31 02:55:34 +03:00
committed by GitHub
parent fc7964fb07
commit 77ecc8ddfe
2 changed files with 39 additions and 36 deletions
@@ -25,6 +25,7 @@ export default function SidebarPerfProbeMonitorTab() {
const analysisPinned = usePipelineOverlayPinned('pipeline:analysis');
const coverPinned = usePipelineOverlayPinned('pipeline:cover');
const cpu = live.cpu;
const cpuSupported = cpu?.supported === true;
const collecting = live.collecting && cpu == null;
const includeThreadGroups = usePerfLiveIncludeThreadGroups();
const peakMemoryKbRef = useRef(1);
@@ -51,14 +52,6 @@ export default function SidebarPerfProbeMonitorTab() {
);
}
if (cpu && !cpu.supported) {
return (
<div className="perf-monitor-empty">
Live CPU/memory monitoring is unavailable on this platform or build.
</div>
);
}
const toggleLive = (id: PerfLiveOverlayPinId) => () => togglePerfLiveOverlayPin(id);
const livePinned = (id: PerfLiveOverlayPinId) => livePins.has(id);
@@ -94,7 +87,13 @@ export default function SidebarPerfProbeMonitorTab() {
/>
</PerfProbeMetricSection>
{cpu && (
{cpu && !cpuSupported && (
<div className="perf-monitor-empty perf-monitor-empty--inline">
Live CPU and RSS sampling is unavailable on this platform. Pipeline, UI rate, and analysis metrics below still work.
</div>
)}
{cpuSupported && cpu && (
<>
<PerfProbeMetricSection title="CPU — processes">
<PerfProbeMetricCard
+31 -27
View File
@@ -96,6 +96,29 @@ function readUiCounters(): { progress: number; waveform: number; home: number }
};
}
function buildAnalysisDiag(): PerfAnalysisDiag {
return {
tracksPerMinute: getAnalysisTracksPerMinute(),
lastTotalMs: snapshot.analysis?.lastTotalMs ?? null,
lastFetchMs: snapshot.analysis?.lastFetchMs ?? null,
lastSeedMs: snapshot.analysis?.lastSeedMs ?? null,
lastBpmMs: snapshot.analysis?.lastBpmMs ?? null,
};
}
function nextDiagRates(
nextCounters: { progress: number; waveform: number; home: number },
now: number,
): PerfDiagRates | null {
if (!prevCounters || prevCountersAt <= 0) return snapshot.diagRates;
const dt = Math.max(0.25, (now - prevCountersAt) / 1000);
return {
progress: (nextCounters.progress - prevCounters.progress) / dt,
waveform: (nextCounters.waveform - prevCounters.waveform) / dt,
home: (nextCounters.home - prevCounters.home) / dt,
};
}
async function pollOnce(): Promise<void> {
const generation = pollGeneration;
const now = Date.now();
@@ -103,17 +126,16 @@ async function pollOnce(): Promise<void> {
const snap = await invoke<ProcSnapshot>('performance_cpu_snapshot', buildPerfCpuSnapshotRequest());
if (generation !== pollGeneration) return;
const nextCounters = readUiCounters();
const diagRates = nextDiagRates(nextCounters, now);
prevCounters = nextCounters;
prevCountersAt = now;
if (!snap.supported) {
setSnapshot({
cpu: { app: 0, webkit: 0, supported: false, memory: [], threadCpu: [] },
diagRates: snapshot.diagRates,
analysis: {
tracksPerMinute: getAnalysisTracksPerMinute(),
lastTotalMs: snapshot.analysis?.lastTotalMs ?? null,
lastFetchMs: snapshot.analysis?.lastFetchMs ?? null,
lastSeedMs: snapshot.analysis?.lastSeedMs ?? null,
lastBpmMs: snapshot.analysis?.lastBpmMs ?? null,
},
diagRates,
analysis: buildAnalysisDiag(),
collecting: false,
updatedAt: now,
});
@@ -160,30 +182,12 @@ async function pollOnce(): Promise<void> {
}
}
const nextCounters = readUiCounters();
let diagRates = snapshot.diagRates;
if (prevCounters && prevCountersAt > 0) {
const dt = Math.max(0.25, (now - prevCountersAt) / 1000);
diagRates = {
progress: (nextCounters.progress - prevCounters.progress) / dt,
waveform: (nextCounters.waveform - prevCounters.waveform) / dt,
home: (nextCounters.home - prevCounters.home) / dt,
};
}
prevCounters = nextCounters;
prevCountersAt = now;
prevProc = snap;
setSnapshot({
cpu,
diagRates,
analysis: {
tracksPerMinute: getAnalysisTracksPerMinute(),
lastTotalMs: snapshot.analysis?.lastTotalMs ?? null,
lastFetchMs: snapshot.analysis?.lastFetchMs ?? null,
lastSeedMs: snapshot.analysis?.lastSeedMs ?? null,
lastBpmMs: snapshot.analysis?.lastBpmMs ?? null,
},
analysis: buildAnalysisDiag(),
collecting: false,
updatedAt: now,
});