Files
gnome-shell-extension-freon/freon@UshakovVasilii_Github.yahoo.com/cpuUsageUtil.js
2026-03-02 02:34:36 +09:00

131 lines
3.6 KiB
JavaScript

import GLib from 'gi://GLib';
export default class CpuUsageUtil {
constructor(intervalSeconds = 2) {
this._updated = false;
this._readings = [];
this._prevSnapshot = null;
this._intervalUsec = 0;
this._lastUpdateUsec = 0;
this.interval = intervalSeconds;
// Take initial snapshot so the first real execute() can compute a delta
this._prevSnapshot = this._readProcStat();
}
get available() {
return this._prevSnapshot !== null;
}
get updated() {
return this._updated;
}
set updated(updated) {
this._updated = updated;
}
execute(callback) {
const nowUsec = GLib.get_monotonic_time();
const remaining = this._intervalUsec - (nowUsec - this._lastUpdateUsec);
if (this._intervalUsec > 0 && this._lastUpdateUsec !== 0 && remaining > 0) {
if (callback)
callback();
return;
}
this._updated = false;
try {
const snapshot = this._readProcStat();
if (!snapshot || !this._prevSnapshot) {
this._prevSnapshot = snapshot;
return;
}
this._readings = [];
const fields = snapshot.get('cpu');
const prev = this._prevSnapshot.get('cpu');
if (fields && prev) {
const idle = (fields.idle + fields.iowait) - (prev.idle + prev.iowait);
const total = fields.total - prev.total;
if (total > 0) {
const usage = 100.0 * (1.0 - idle / total);
this._readings.push({
label: 'CPU Usage',
usage: Math.max(0, Math.min(100, usage)),
});
}
}
this._prevSnapshot = snapshot;
} catch (e) {
logError(e, '[FREON] Failed to read CPU usage');
this._readings = [];
} finally {
this._lastUpdateUsec = nowUsec;
this._updated = true;
if (callback)
callback();
}
}
get usage() {
return this._readings;
}
destroy() {
this._readings = [];
this._prevSnapshot = null;
this._lastUpdateUsec = 0;
}
set interval(seconds) {
const clamped = Math.max(1, seconds | 0);
this._intervalUsec = clamped * 1000000;
this._lastUpdateUsec = 0;
}
_readProcStat() {
let ok, contents;
try {
[ok, contents] = GLib.file_get_contents('/proc/stat');
} catch (e) {
return null;
}
if (!ok)
return null;
const text = new TextDecoder().decode(contents);
const result = new Map();
for (const line of text.split('\n')) {
if (!line.startsWith('cpu'))
continue;
const parts = line.trim().split(/\s+/);
const name = parts[0];
// user nice system idle iowait irq softirq steal
const user = parseInt(parts[1]) || 0;
const nice = parseInt(parts[2]) || 0;
const system = parseInt(parts[3]) || 0;
const idle = parseInt(parts[4]) || 0;
const iowait = parseInt(parts[5]) || 0;
const irq = parseInt(parts[6]) || 0;
const softirq = parseInt(parts[7]) || 0;
const steal = parseInt(parts[8]) || 0;
const total = user + nice + system + idle + iowait + irq + softirq + steal;
result.set(name, { idle, iowait, total });
}
return result.size > 0 ? result : null;
}
}