[AGS] SysInfo: Re-Structure for better perf

This commit is contained in:
Janis Hutz 2025-04-26 15:32:47 +02:00
parent 090492ae51
commit 11c961bfe7
2 changed files with 149 additions and 128 deletions

View File

@ -1,88 +1,6 @@
import { exec, execAsync, interval, Variable } from "astal";
import { exec } from "astal";
import { Gtk } from "astal/gtk4";
const FETCH_INTERVAL = 2000;
const cpuUtil = Variable("0%");
const ramUtil = Variable("0%");
const ramUsed = Variable("0MiB");
const gpuUtil = Variable("0%");
let gpuName = "card1";
let enabled = false;
const refreshStats = (): Stats => {
gpuName = exec(`/bin/bash -c "ls /sys/class/drm/ | grep '^card[0-9]*$'"`);
const cpuNameInSensors = "CPUTIN";
const stats = {
kernel: exec("uname -sr"),
cpuTemp: exec(
`/bin/bash -c "sensors | grep -m1 ${cpuNameInSensors} | awk '{print $2}'"`,
),
cpuClk: exec(
`awk '/cpu MHz/ {sum+=$4; ++n} END {print sum/n " MHz"}' /proc/cpuinfo`,
),
gpuTemp: exec(
`/bin/bash -c "sensors | grep -E 'edge' | awk '{print $2}'"`,
),
gpuClk: exec(
`/bin/bash -c "cat /sys/class/drm/${gpuName}/device/pp_dpm_sclk | grep '\\*' | awk '{print $2 $3}'"`,
),
vram:
Math.round(
parseInt(
exec(
`cat /sys/class/drm/${gpuName}/device/mem_info_vram_used`,
),
) /
1024 /
1024,
) + "MiB",
availableVRAM:
Math.round(
parseInt(
exec(
`cat /sys/class/drm/${gpuName}/device/mem_info_vram_total`,
),
) /
1024 /
1024,
) + "MiB",
};
return stats;
};
const systemStats: Variable<Stats> = Variable(refreshStats());
const availableFeatures = {
cpu: true,
ram: true,
};
const featureTest = () => {
// Check if awk & sed are available
try {
exec("awk -V");
exec("sed --version");
enabled = true;
} catch (e) {
printerr(
"[ SysInfo ] AWK or SED missing! No system info will be available",
);
enabled = false;
return;
}
// Check if mpstat is available
try {
exec("mpstat -V");
} catch (e) {
availableFeatures.cpu = false;
printerr(
"[ SysInfo ] Feature Test for CPU info failed. mpstat from the sysstat package missing!",
);
}
};
import sysinfo from "../sysinfo";
const info = () => {
return (
@ -96,12 +14,12 @@ const info = () => {
vexpand
halign={Gtk.Align.START}
hexpand
label={ramUsed(used => {
return "RAM: " + used + ` (${ramUtil.get()}%)`;
label={sysinfo.ramUsed(used => {
return "RAM: " + used + ` (${sysinfo.ramUtil.get()}%)`;
})}
></label>
<label
label={systemStats(stats => {
label={sysinfo.systemStats(stats => {
return `CPU: ${stats.cpuTemp}, ${stats.cpuClk}
GPU: ${stats.gpuTemp}, ${stats.gpuClk} (${stats.vram} / ${stats.availableVRAM})
Kernel: ${stats.kernel}`;
@ -125,69 +43,35 @@ const SystemInformationPanel = () => {
return popover;
};
const sysInfoFetcher = () => {
if (enabled) {
if (availableFeatures.cpu) {
execAsync(`/bin/fish -c cpu-utilization`).then(v => {
cpuUtil.set("" + Math.round(parseFloat(v)));
}).catch( e => {
console.error( e );
} );
}
if (availableFeatures.ram) {
execAsync(
`/bin/bash -c "free | awk '/Mem:/ {print $3 \\" \\" $2}'"`,
).then( v => {
const util = parseInt( v.split( ' ' )[ 0 ] );
const available = parseInt( v.split( ' ' )[ 1 ] );
ramUtil.set( "" + Math.round( available / util ) );
ramUsed.set( `${Math.round( util / 1024 / 1024 )}MiB used of ${Math.round( available / 1024 / 1024 )}MiB` );
} ).catch( e => {
console.error( e );
} );
ramUsed.set(
exec(
`/bin/bash -c \"free -h | awk '/^Mem:/ {print $3 \\" used of \\" $2}'\"`,
)
.replaceAll("Gi", "GiB")
.replaceAll("Mi", "MiB"),
);
}
gpuUtil.set(exec("cat /sys/class/drm/card1/device/gpu_busy_percent"));
}
};
const panel = SystemInformationPanel();
const SystemInfo = () => {
featureTest();
sysinfo.startSysInfoFetcher();
const openSysInfo = async () => {
panel.popup();
systemStats.set(refreshStats());
sysinfo.refreshStats();
};
if (enabled) {
sysInfoFetcher();
interval(FETCH_INTERVAL, sysInfoFetcher);
if (sysinfo.enabled) {
return (
<button
onClicked={() => openSysInfo()}
child={
<box tooltipText={ramUsed(v => v)}>
<box tooltipText={sysinfo.ramUsed(v => v)}>
<image
iconName={"power-profile-performance-symbolic"}
marginEnd={1}
></image>
<label
label={cpuUtil(util => util)}
label={sysinfo.cpuUtil(util => util)}
marginEnd={5}
></label>
<image iconName={"histogram-symbolic"}></image>
<label label={ramUtil(util => util)}></label>
<label label={sysinfo.ramUtil(util => util)}></label>
<image iconName={"show-gpu-effects-symbolic"}></image>
<label label={gpuUtil(util => util)}></label>
<label label={sysinfo.gpuUtil(util => util)}></label>
{panel}
</box>
}

View File

@ -0,0 +1,137 @@
import { exec, execAsync, interval, Variable } from "astal";
const FETCH_INTERVAL = 2000;
const cpuUtil = Variable("0%");
const ramUtil = Variable("0%");
const ramUsed = Variable("0MiB");
const gpuUtil = Variable("0%");
let gpuName = "card1";
let enabled = true;
const getStats = (): Stats => {
gpuName = exec(`/bin/bash -c "ls /sys/class/drm/ | grep '^card[0-9]*$'"`);
const cpuNameInSensors = "CPUTIN";
const stats = {
kernel: exec("uname -sr"),
cpuTemp: exec(
`/bin/bash -c "sensors | grep -m1 ${cpuNameInSensors} | awk '{print $2}'"`,
),
cpuClk: exec(
`awk '/cpu MHz/ {sum+=$4; ++n} END {print sum/n " MHz"}' /proc/cpuinfo`,
),
gpuTemp: exec(
`/bin/bash -c "sensors | grep -E 'edge' | awk '{print $2}'"`,
),
gpuClk: exec(
`/bin/bash -c "cat /sys/class/drm/${gpuName}/device/pp_dpm_sclk | grep '\\*' | awk '{print $2 $3}'"`,
),
vram:
Math.round(
parseInt(
exec(
`cat /sys/class/drm/${gpuName}/device/mem_info_vram_used`,
),
) /
1024 /
1024,
) + "MiB",
availableVRAM:
Math.round(
parseInt(
exec(
`cat /sys/class/drm/${gpuName}/device/mem_info_vram_total`,
),
) /
1024 /
1024,
) + "MiB",
};
return stats;
};
const systemStats: Variable<Stats> = Variable(getStats());
const availableFeatures = {
cpu: true,
ram: true,
};
const refreshStats = () => {
systemStats.set(getStats());
}
const featureTest = () => {
print('[SysInfo] Feature test started...');
// Check if awk & sed are available
try {
exec("awk -V");
exec("sed --version");
} catch (e) {
printerr(
"[ SysInfo ] AWK or SED missing! No system info will be available",
);
enabled = false;
return;
}
// Check if mpstat is available
try {
exec("mpstat -V");
} catch (e) {
availableFeatures.cpu = false;
printerr(
"[ SysInfo ] Feature Test for CPU info failed. mpstat from the sysstat package missing!",
);
}
print('[SysInfo] Feature test complete');
};
const sysInfoFetcher = () => {
if (enabled) {
if (availableFeatures.cpu) {
execAsync(`/bin/fish -c cpu-utilization`).then(v => {
cpuUtil.set("" + Math.round(parseFloat(v)));
}).catch(e => {
console.error(e);
});
}
if (availableFeatures.ram) {
execAsync(
`/bin/bash -c "free | awk '/Mem:/ {print $3 \\" \\" $2}'"`,
).then(v => {
const util = parseInt(v.split(' ')[0]);
const available = parseInt(v.split(' ')[1]);
ramUtil.set("" + Math.round(util / available * 100));
ramUsed.set(`${Math.round(util / 1024 / 1024 * 10) / 10} GiB of ${Math.round(available / 1024 / 1024 * 10) / 10} GiB used`);
}).catch(e => {
console.error(e);
});
}
gpuUtil.set(exec("cat /sys/class/drm/card1/device/gpu_busy_percent"));
}
};
let sysInfoFetcherRunning = false;
const startSysInfoFetcher = () => {
if (!sysInfoFetcherRunning) {
sysInfoFetcherRunning = true;
featureTest();
if (enabled) {
// Start interval
interval(FETCH_INTERVAL, sysInfoFetcher);
}
}
}
export default {
startSysInfoFetcher,
enabled,
gpuUtil,
cpuUtil,
ramUsed,
ramUtil,
refreshStats,
systemStats
}