Skip to content

hwmonitor@sylfurd v1.4.0: Add optional GPU utilization and GPU memory graphs (NVIDIA + AMD) - #8914

Open
wiebelhaus wants to merge 1 commit into
linuxmint:masterfrom
wiebelhaus:hwmonitor-gpu-graphs
Open

hwmonitor@sylfurd v1.4.0: Add optional GPU utilization and GPU memory graphs (NVIDIA + AMD)#8914
wiebelhaus wants to merge 1 commit into
linuxmint:masterfrom
wiebelhaus:hwmonitor-gpu-graphs

Conversation

@wiebelhaus

Copy link
Copy Markdown

What

Adds two new optional graphs to the Graphical hardware monitor: GPU (utilization %) and GMEM (GPU memory usage). Both are disabled by default and are enabled from a new "GPU" tab in the applet settings, with the same options as the existing graphs (size, custom label, detail label).

How

A shared poller auto-detects the GPU vendor once, then feeds both graphs:

  • AMD (amdgpu driver): read directly from sysfs (gpu_busy_percent, mem_info_vram_used, mem_info_vram_total). Instant reads, no subprocess.
  • NVIDIA: nvidia-smi --query-gpu=... spawned asynchronously via Gio.Subprocess, so the Cinnamon UI thread never blocks. One subprocess per refresh tick regardless of how many GPU graphs are enabled; getData() returns the previous sample.
  • No supported GPU: providers report "n/a" and return 0; since the graphs are off by default, machines without a GPU are unaffected.

Intel GPUs are not supported: the i915/xe drivers do not expose a utilization counter readable without elevated permissions (intel_gpu_top needs perf access), and iGPU memory is shared system RAM. This is documented in the README.

Changes

  • 3.8/providers.js: shared GpuPoller + GpuUtilDataProvider / GpuMemDataProvider
  • 3.8/applet.js: settings binds, graph creation, theme object entries
  • 3.8/graph.js: custom label cases for the two new graph types
  • 3.8/settings-schema.json: new GPU page with two sections (all defaults off)
  • README.md: GPU support and requirements section
  • metadata.json: version 1.3.4 -> 1.4.0

Testing

Tested on Linux Mint 22.3 (Cinnamon 6.6.5) with an NVIDIA GTX 1650 (nvidia-smi backend): graphs track utilization and VRAM correctly at 1s refresh, detail labels show % and formatted bytes, settings tab works, no errors in ~/.xsession-errors, and disabling the graphs removes them cleanly. The AMD path follows the documented amdgpu sysfs interface (same fields used by tools like radeontop); I do not have an AMD card in this machine, so review from an amdgpu user would be welcome.

🤖 Generated with Claude Code

https://claude.ai/code/session_01UUKno4V7XVo8nv95eJghdj

… graphs (NVIDIA + AMD)

Adds two new optional graphs (disabled by default):
- GPU: GPU utilization percentage
- GMEM: GPU memory usage

Data comes from a shared poller that auto-detects the vendor:
AMD GPUs are read instantly from sysfs (amdgpu gpu_busy_percent /
mem_info_vram_*); NVIDIA GPUs use nvidia-smi spawned asynchronously
so the UI thread never blocks (one subprocess per refresh tick,
shared by both graphs). Machines without a supported GPU show n/a
and the graphs stay disabled by default. Intel is not supported
because i915/xe expose no unprivileged utilization counter.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UUKno4V7XVo8nv95eJghdj
@github-actions

Copy link
Copy Markdown
Contributor

Best-practices scanner

This is a regex-based check for API usage that can pose security, performance or
maintainability issues, or that may already be provided by Cinnamon. Most findings
are advisory and do not automatically disqualify a pull request.

This check is not perfect and will not replace a normal review.


Found 2 potential issue(s):

⚠️ WARNING

⚠️ sync_file_get_contents

hwmonitor@sylfurd/files/hwmonitor@sylfurd/3.8/providers.js:378

let [success, contents] = GLib.file_get_contents(path);

Synchronous file_get_contents() blocks the main loop.
Use Gio.File.load_contents_async() instead.

⚠️ sync_file_test

hwmonitor@sylfurd/files/hwmonitor@sylfurd/3.8/providers.js:363

if (GLib.file_test(path + "/gpu_busy_percent", GLib.FileTest.EXISTS)) {

file_test() is a synchronous stat call that can block on slow/network filesystems.
Prefer attempting the operation and handling a Gio.IOErrorEnum.NOT_FOUND error instead.


Automated pattern check.

@wiebelhaus

Copy link
Copy Markdown
Author

Regarding the two scanner warnings (sync_file_get_contents and sync_file_test in the new GPU code): both call sites operate exclusively on sysfs paths (/sys/class/drm/cardN/device/...), which are kernel-memory-backed virtual files - reads complete in microseconds and never touch disk or network, so they cannot meaningfully block the main loop. The file_test scan additionally runs only once per session (vendor detection is cached).

This is also consistent with the applet's existing code: BatteryProvider uses the same GLib.file_get_contents-on-sysfs pattern for /sys/class/power_supply/BAT0/capacity.

Where blocking is a real risk - the NVIDIA path, which spawns a subprocess - the implementation is fully async (Gio.Subprocess.communicate_utf8_async), with the provider returning the previous sample so the UI thread never waits.

Happy to convert the sysfs reads to Gio.File.load_contents_async if the maintainers prefer strict compliance with the scanner.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant