feat(perf): cover pipeline throughput (cpm) in performance probe (#945)

* feat(perf): cover pipeline throughput (cpm) in performance probe

Mirror the analysis pipeline's tpm for covers. A new coverPerfStore samples the
backfill `done` progress from cover:library-progress events and derives a rolling
one-minute covers-per-minute rate. Surfaced as a live diag in perfLiveStore, a
pinnable "Cover backfill" throughput card in the Monitor tab, and a cpm row in
the Cover pipeline overlay block.

* docs(changelog): note cover pipeline cpm metric (PR #945)

Add CHANGELOG entry and credits line for the cover-pipeline covers-per-minute
throughput metric in the Performance Probe.
This commit is contained in:
cucadmuh
2026-06-02 11:05:28 +03:00
committed by GitHub
parent 42aec6720c
commit c6df05e576
11 changed files with 279 additions and 4 deletions
+20
View File
@@ -31,6 +31,8 @@ import {
usePerfOverlayMode,
} from '../utils/perf/perfOverlayMode';
import { useAnalysisPerfListener } from '../hooks/useAnalysisPerfListener';
import { useCoverPerfListener } from '../hooks/useCoverPerfListener';
import { getCoverCachedPerMinute } from '../utils/perf/coverPerfStore';
const SAMPLE_MS = 500;
const TPM_REFRESH_MS = 500;
@@ -66,6 +68,7 @@ export default function FpsOverlay() {
const overlayAppearance = usePerfOverlayAppearance();
const [fps, setFps] = useState(0);
const [tpm, setTpm] = useState(0);
const [cpm, setCpm] = useState(0);
const [queueStats, setQueueStats] = useState<AnalysisPipelineQueueStatsDto | null>(null);
const [coverQueueLines, setCoverQueueLines] = useState<string[]>([]);
const last = useAnalysisPerfLast();
@@ -93,6 +96,7 @@ export default function FpsOverlay() {
);
useAnalysisPerfListener(showAnalysisPerfOverlay || livePins.has('analysis:tpm') || livePins.has('analysis:last'));
useCoverPerfListener(showCoverPerfOverlay || livePins.has('cover:cpm'));
useEffect(() => {
if (!showAnalysisPerfOverlay) {
@@ -128,6 +132,17 @@ export default function FpsOverlay() {
};
}, [showAnalysisPerfOverlay]);
useEffect(() => {
if (!showCoverPerfOverlay) {
setCpm(0);
return;
}
const refresh = () => setCpm(getCoverCachedPerMinute());
refresh();
const id = window.setInterval(refresh, TPM_REFRESH_MS);
return () => window.clearInterval(id);
}, [showCoverPerfOverlay]);
useEffect(() => {
if (!showCoverPerfOverlay) {
setCoverQueueLines([]);
@@ -252,6 +267,11 @@ export default function FpsOverlay() {
{showCoverPerfOverlay && (
<div className="fps-overlay__block">
<div className="fps-overlay__block-title">Cover pipeline</div>
<div className="fps-overlay__row">
{cpm.toFixed(1)}
{' '}
<span className="fps-overlay__unit">cpm</span>
</div>
{coverQueueLines.length > 0 ? coverQueueLines.map(line => (
<div key={line} className="fps-overlay__row fps-overlay__row--steps">
{line}
@@ -221,6 +221,21 @@ export default function SidebarPerfProbeMonitorTab() {
)}
</PerfProbeMetricSection>
)}
{live.cover && (
<PerfProbeMetricSection title="Cover backfill" defaultOpen={false}>
<PerfProbeMetricCard
label="Throughput"
value={live.cover.cachedPerMinute.toFixed(1)}
unit="cpm"
detail={live.cover.total > 0
? `${live.cover.done.toLocaleString()} / ${live.cover.total.toLocaleString()} cached`
: 'covers cached per minute'}
pinned={livePinned('cover:cpm')}
onTogglePin={toggleLive('cover:cpm')}
/>
</PerfProbeMetricSection>
)}
</div>
);
}