sysstat: network stats simplification without local history cache + adjusting existing polling intervals

This commit is contained in:
Lemmy
2026-02-02 08:57:09 -05:00
parent a8853b78f5
commit 93e34bcdb3
4 changed files with 39 additions and 76 deletions
+28
View File
@@ -0,0 +1,28 @@
import QtQuick
import Quickshell
QtObject {
id: root
function migrate(adapter, logger, rawJson) {
logger.i("Migration47", "Removing network_stats.json cache and updating polling intervals");
// Remove the network_stats.json cache file (no longer used - autoscaling from history now)
const shellName = "noctalia";
const cacheDir = Quickshell.env("NOCTALIA_CACHE_DIR") || (Quickshell.env("XDG_CACHE_HOME") || Quickshell.env("HOME") + "/.cache") + "/" + shellName + "/";
const networkStatsFile = cacheDir + "network_stats.json";
Quickshell.execDetached(["rm", "-f", networkStatsFile]);
// Update polling intervals to 1000ms for smoother graphs (only if currently slower)
if (adapter.systemMonitor.cpuPollingInterval > 1000)
adapter.systemMonitor.cpuPollingInterval = 1000;
if (adapter.systemMonitor.memPollingInterval > 1000)
adapter.systemMonitor.memPollingInterval = 1000;
if (adapter.systemMonitor.networkPollingInterval > 1000)
adapter.systemMonitor.networkPollingInterval = 1000;
logger.d("Migration47", "Removed network_stats.json and adjusted polling intervals");
return true;
}
}
+3 -1
View File
@@ -20,7 +20,8 @@ QtObject {
43: migration43Component,
44: migration44Component,
45: migration45Component,
46: migration46Component
46: migration46Component,
47: migration47Component
})
// Migration components
@@ -38,4 +39,5 @@ QtObject {
property Component migration44Component: Migration44 {}
property Component migration45Component: Migration45 {}
property Component migration46Component: Migration46 {}
property Component migration47Component: Migration47 {}
}
+1 -1
View File
@@ -25,7 +25,7 @@ Singleton {
- Default cache directory: ~/.cache/noctalia
*/
readonly property alias data: adapter // Used to access via Settings.data.xxx.yyy
readonly property int settingsVersion: 46
readonly property int settingsVersion: 47
readonly property bool isDebug: Quickshell.env("NOCTALIA_DEBUG") === "1"
readonly property string shellName: "noctalia"
readonly property string configDir: Quickshell.env("NOCTALIA_CONFIG_DIR") || (Quickshell.env("XDG_CONFIG_HOME") || Quickshell.env("HOME") + "/.config") + "/" + shellName + "/"
+7 -74
View File
@@ -70,7 +70,7 @@ Singleton {
property real gpuTempHistoryMin: 100
property real gpuTempHistoryMax: 0
property real memHistoryMax: 0
// Network uses existing rxMaxSpeed/txMaxSpeed (7-day learned peaks)
// Network uses autoscaling from current history window
// Disk is always 0-100%
// History management - called from update functions, not change handlers
@@ -150,17 +150,17 @@ Singleton {
txSpeedHistory = txH;
}
// Network max speed tracking (learned over time, cached for 7 days)
// Network max speed tracking (autoscales from current history window)
readonly property real rxMaxSpeed: {
const peaks = networkStatsAdapter.rxPeaks || [];
return peaks.length > 0 ? Math.max(...peaks.map(p => p.speed)) : 0;
const max = Math.max(...rxSpeedHistory);
return max > 0 ? max : 1024; // Minimum 1 KB/s floor
}
readonly property real txMaxSpeed: {
const peaks = networkStatsAdapter.txPeaks || [];
return peaks.length > 0 ? Math.max(...peaks.map(p => p.speed)) : 0;
const max = Math.max(...txSpeedHistory);
return max > 0 ? max : 1024; // Minimum 1 KB/s floor
}
// Ready-to-use ratios based on learned maximums (0..1 range)
// Ready-to-use ratios based on current maximums (0..1 range)
readonly property real rxRatio: rxMaxSpeed > 0 ? Math.min(1, rxSpeed / rxMaxSpeed) : 0
readonly property real txRatio: txMaxSpeed > 0 ? Math.min(1, txSpeed / txMaxSpeed) : 0
@@ -251,52 +251,6 @@ Singleton {
property var foundGpuSensors: [] // [{hwmonPath, type, hasDedicatedVram}]
property int gpuVramCheckIndex: 0
// --------------------------------------------
// Network speed stats cache (7-day rolling window)
property string networkStatsFile: Settings.cacheDir + "network_stats.json"
FileView {
id: networkStatsView
path: root.networkStatsFile
printErrors: false
JsonAdapter {
id: networkStatsAdapter
property var rxPeaks: []
property var txPeaks: []
}
onLoadFailed: {
networkStatsAdapter.rxPeaks = [];
networkStatsAdapter.txPeaks = [];
}
onLoaded: {
root.pruneExpiredPeaks();
}
}
Timer {
id: networkStatsSaveDebounce
interval: 1000
onTriggered: networkStatsView.writeAdapter()
}
function pruneExpiredPeaks() {
const sevenDaysMs = 7 * 24 * 60 * 60 * 1000;
const cutoff = Date.now() - sevenDaysMs;
const rxBefore = (networkStatsAdapter.rxPeaks || []).length;
const txBefore = (networkStatsAdapter.txPeaks || []).length;
networkStatsAdapter.rxPeaks = (networkStatsAdapter.rxPeaks || []).filter(p => p.timestamp > cutoff);
networkStatsAdapter.txPeaks = (networkStatsAdapter.txPeaks || []).filter(p => p.timestamp > cutoff);
// Save if any were pruned
if (networkStatsAdapter.rxPeaks.length !== rxBefore || networkStatsAdapter.txPeaks.length !== txBefore) {
networkStatsSaveDebounce.restart();
}
}
// --------------------------------------------
Component.onCompleted: {
Logger.i("SystemStat", "Service started with custom polling intervals");
@@ -1006,27 +960,6 @@ Singleton {
root.rxSpeed = Math.round(rxDiff / timeDiff); // Speed in Bytes/s
root.txSpeed = Math.round(txDiff / timeDiff);
// Record new peaks if higher than current max (for adaptive ratio calculation)
const now = Date.now();
if (root.rxSpeed > root.rxMaxSpeed) {
networkStatsAdapter.rxPeaks = [...(networkStatsAdapter.rxPeaks || []),
{
speed: root.rxSpeed,
timestamp: now
}
];
networkStatsSaveDebounce.restart();
}
if (root.txSpeed > root.txMaxSpeed) {
networkStatsAdapter.txPeaks = [...(networkStatsAdapter.txPeaks || []),
{
speed: root.txSpeed,
timestamp: now
}
];
networkStatsSaveDebounce.restart();
}
}
}