From ffd6b594724d7aadd2cd08782485ece9a2aa5331 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Sat, 17 Oct 2026 11:57:30 +0200 Subject: perf: sample everything always, not only while the page is open Per-core load, the network rate, VRAM and the fan used to run only while a PerfPanel existed, and closing the page cleared them. Opening the drawer therefore always showed a fresh first sample and an empty network graph, which made the page not very useful as a glance at what just happened. Everything now samples for the whole session, so the graph opens on the last minute of history. The cost is the VRAM fdinfo scan, ~14ms every 2s, now unconditional; a ponytail note beside it says to gate it on the panel again if that shows up. The LAN address and the public IP check run once at startup instead of on each page open. Co-Authored-By: Claude Opus 5.5 --- desktop/modules/perf/Perf.qml | 51 ++++++++++++-------------------------- desktop/modules/perf/PerfPanel.qml | 4 --- desktop/modules/perf/README.md | 6 ++--- 3 files changed, 19 insertions(+), 42 deletions(-) (limited to 'desktop/modules') diff --git a/desktop/modules/perf/Perf.qml b/desktop/modules/perf/Perf.qml index 6216959..9ebfe45 100644 --- a/desktop/modules/perf/Perf.qml +++ b/desktop/modules/perf/Perf.qml @@ -18,19 +18,14 @@ import QtQml import "../.." import "Perf.js" as P -// The numbers behind the performance panel and the status pill's icon. CPU, -// RAM, temperatures and disks are sampled always, so the icon can warn while -// the panel is closed; per-core load, the network rate, VRAM and the fan only -// while `detailed`, which is any PerfPanel existing (the drawer page). +// The numbers behind the performance panel and the status pill's icon, all +// sampled always: the icon warns while the panel is closed, and the panel +// opens on history (the network graph) rather than an empty first sample. // /proc and /sys are FileViews reloaded on a timer, no subprocess; df, the // fdinfo scan, ip and curl are Processes. Singleton { id: root - // PerfPanel instances alive; each counts itself in and out. - property int viewers: 0 - readonly property bool detailed: viewers > 0 - // ponytail: host constants, as conky had them. One mount per NFS server // (Library and Slackware are one export, so are shared and backup); br0 // is a bridge, so VM-to-host copies show in the graph; xe puts no VRAM @@ -56,13 +51,13 @@ Singleton { property var hwmon: ({}) // chip name -> /sys/class/hwmon/hwmonN property string cpuModel: "" property var load: null // aggregate percent - property var cores: [] // percent per core, while detailed + property var cores: [] // percent per core property var mem: null // {total, used} bytes property var temps: [] // [{label, value, warn, crit}], value null if unread property var disks: [] // Perf.js df rows - property var vram: null // bytes, while detailed - property var fan: null // rpm, while detailed - property var rx: [] // bytes/s, newest last, while detailed + property var vram: null // bytes + property var fan: null // rpm + property var rx: [] // bytes/s, newest last property var tx: [] property string lan: "" property var pub: null // {ip, fetched} @@ -100,18 +95,9 @@ Singleton { pubProc.running = true; } - onDetailedChanged: { - if (detailed) { - if (!root.lan) lanProc.running = true; - root.fetchPubip(); - } else { - root.cores = []; - root.rx = []; - root.tx = []; - root.prevNet = null; - root.vram = null; - root.fan = null; - } + Component.onCompleted: { + lanProc.running = true; + root.fetchPubip(); } // --- /proc and /sys --------------------------------------------------- @@ -162,7 +148,6 @@ Singleton { stdout: StdioCollector { onStreamFinished: root.hwmon = P.hwmonMap(text) } } - // CPU, RAM and temperatures always; the fan and VRAM while detailed. Timer { interval: 2000 running: true @@ -174,9 +159,7 @@ Singleton { stat.reload(); const cur = P.cpuTimes(stat.text()); root.load = P.load(root.prevCpu[0], cur[0]); - root.cores = root.detailed - ? cur.slice(1).map((c, i) => P.load(root.prevCpu[i + 1], c) ?? 0) - : []; + root.cores = cur.slice(1).map((c, i) => P.load(root.prevCpu[i + 1], c) ?? 0); root.prevCpu = cur; meminfo.reload(); @@ -196,15 +179,13 @@ Singleton { } root.temps = t; - if (root.detailed) { - if (fanView.path) { fanView.reload(); root.fan = root.num(fanView); } - if (!vramProc.running) vramProc.running = true; - } + if (fanView.path) { fanView.reload(); root.fan = root.num(fanView); } + if (!vramProc.running) vramProc.running = true; } } - // ponytail: a shell glob over every fd on the system, ~14ms; only while - // the panel is open. Only the user's own processes are readable, so a + // ponytail: a shell glob over every fd on the system, ~14ms every 2s, + // always; gate it on the panel again if that shows up. Only the user's own processes are readable, so a // system service's GPU use is not counted, as in conky. Process { id: vramProc @@ -217,7 +198,7 @@ Singleton { Timer { interval: 1000 - running: root.detailed + running: true repeat: true triggeredOnStart: true onTriggered: { diff --git a/desktop/modules/perf/PerfPanel.qml b/desktop/modules/perf/PerfPanel.qml index de9021b..aa2e49f 100644 --- a/desktop/modules/perf/PerfPanel.qml +++ b/desktop/modules/perf/PerfPanel.qml @@ -34,10 +34,6 @@ Column { function sensor(label) { return Perf.temps.find(t => t.label === label) || { value: null, warn: 0, crit: 0 }; } - // Detailed sampling (per-core, network, VRAM, fan) runs while the panel - // exists, which is while the drawer page is shown. - Component.onCompleted: Perf.viewers++ - Component.onDestruction: Perf.viewers-- function pct(part, whole) { return part === null || !whole ? null : 100 * part / whole; } function last(list) { return list.length ? list[list.length - 1] : null; } diff --git a/desktop/modules/perf/README.md b/desktop/modules/perf/README.md index dea5a7e..bd9ebfb 100644 --- a/desktop/modules/perf/README.md +++ b/desktop/modules/perf/README.md @@ -26,9 +26,9 @@ into the LAN depends on the ISP's fixed address. The fetch is `~/.cache/udt/pubip.txt`, the file conky's sampler used. A failed fetch is never a mismatch: the old value goes stale after 4 hours and shows as a dash. -CPU, RAM, temperatures and disks are sampled always. Per-core load, the -network rate, VRAM (a scan of every fdinfo, ~14ms) and the fan run only while -the page is open. The mount list, `br0`, the GPU name and the 12 GiB VRAM +Everything is sampled always, including per-core load, the network rate, +VRAM (a scan of every fdinfo, ~14ms every 2s) and the fan, so the page opens +on the last minute of network history instead of an empty graph. The mount list, `br0`, the GPU name and the 12 GiB VRAM size are constants in `Perf.qml`. The cache card runs `du -B1 -d1` once each time the page opens, 28ms over -- cgit v1.2.3