From fda4e7847bb5dc985404269c81400eead52b0181 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Thu, 12 Nov 2026 19:07:18 +0100 Subject: feat(perf): show GPU render and compute load xe exposes no busy percentage, but its DRM fdinfo carries per-engine cycle counters. vram.sh becomes gpu.sh: the same scan also sums drm-cycles-rcs/ccs per client and prints them with the GPU's cycle counter, and Perf.js turns two scans into a percentage per engine. The GPU card's headline is now the busier engine, with render (games) and compute (local LLMs) as bars, then VRAM, temperature and fan. Co-Authored-By: Claude Opus 5.5 --- desktop/modules/perf/Perf.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'desktop/modules/perf/Perf.js') diff --git a/desktop/modules/perf/Perf.js b/desktop/modules/perf/Perf.js index eb0dbd7..b94e5b6 100644 --- a/desktop/modules/perf/Perf.js +++ b/desktop/modules/perf/Perf.js @@ -44,6 +44,24 @@ function load(prev, cur) { return Math.max(0, Math.min(100, 100 * (1 - (cur.idle - prev.idle) / dt))); } +// gpu.sh's line as numbers: [vram, rcs busy, rcs clock, ccs busy, ccs clock], +// null when it printed nothing. +function gpuSample(text) { + const n = text.trim().split(/\s+/).map(Number); + return n.length === 5 && n.every(Number.isFinite) ? n : null; +} + +// {render, compute} percent busy between two gpuSample()s, each null when +// its clock did not move. A client exiting mid-sample takes its cycles with +// it, so a dip below zero is clamped. +function gpuLoad(prev, cur) { + const pct = (b, c) => { + if (!prev || !cur || cur[c] <= prev[c]) return null; + return Math.max(0, Math.min(100, 100 * (cur[b] - prev[b]) / (cur[c] - prev[c]))); + }; + return { render: pct(1, 2), compute: pct(3, 4) }; +} + // {total, used} in bytes; used is MemTotal - MemAvailable. function meminfo(text) { const kb = key => { -- cgit v1.2.3