Skip to content

feat(local): show live CPU, RAM and GPU usage above Studio - #2092

Merged
MODSetter merged 1 commit into
devfrom
feat/local-resource-usage
Sep 30, 2026
Merged

MODSetter merged 1 commit into
devfrom
feat/local-resource-usage

Conversation

@MODSetter

@MODSetter MODSetter commented Sep 30, 2026 •

Copy link
Copy Markdown
Owner

What

A Resources panel at the top of the desktop app's right column, above Studio, showing live:

  • CPU, RAM, VRAM and GPU load for the machine, each bar split into SurfSense's share (chart-1), other apps and free. The machine figure turns amber at 90% or more for RAM and VRAM.
  • A per-engine breakdown behind the chevron: CPU, RAM and VRAM for llama.cpp, stable-diffusion.cpp, audio.cpp, the backend and the interface, with "Not running" for a runtime that is not up.

How it works:

  • API: GET /system/usage (modules/resource_usage/). Electron passes its own pid as SURFSENSE_LOCAL_SHELL_PID. Every process under it counts as the app, labelled by the child of the shell that started its branch, so llama-server's per-model workers count as llama.cpp.
  • CPU and RAM: from psutil. RAM is resident size (Task Manager's working set).
  • Graphics, per platform:
    • Windows: DXGI for adapters, and the GPU performance counters Task Manager reads for usage. Vendor neutral.
    • Linux: NVML for NVIDIA, amdgpu sysfs plus DRM fdinfo for AMD.
    • macOS: ioreg, read as unified memory, so there is no VRAM row.
  • Frontend: features/resources/ polls every 2 s, only while the right panel is open and the window is visible. A response it can't read shows "Usage unavailable" instead of breaking the dashboard.
  • Docs and translations: new docs/architecture/resource-usage.md, overview updated. 25 strings in all 10 catalogs.

Why

llama.cpp, stable-diffusion.cpp and audio.cpp all compete for the same RAM and VRAM. When generation slows or a model spills, users can't tell whether SurfSense or something else is holding the memory. This panel shows it at a glance.

Fixes # (no issue)

Process note: CONTRIBUTING asks for a proposal PR before a new feature. This one went straight to code with its architecture doc, so accepting it means accepting the design here.

How to test

Automated:

cd surfsense_local/backend && uv run pytest tests/unit/resource_usage tests/integration/resource_usage
cd surfsense_local/frontend && pnpm vitest run --environment jsdom src/features/resources src/features/dashboard
cd surfsense_local/electron && pnpm test

Manual (cd surfsense_local/electron && pnpm dev):

  1. The Resources card sits above Studio. Load a chat model: VRAM's SurfSense share and llama.cpp's VRAM row rise.
  2. Open the breakdown with the chevron; it stays open across reloads. Install or switch a model: llama-server restarts, and it still shows in the next sample.
  3. Close the right panel: requests to /system/usage stop.

Verified on Windows 11 with an RTX 3080, against a running dev app. llama-server held 5.5 GB of the 7.2 GB in use, and the interface 0.05 GB. A sample takes about 40 ms, most of it psutil's process snapshot.

Known gaps, also in the doc:

  • The Linux and macOS readers are unit-tested against recorded output only, not run on real hardware.
  • Intel discrete GPUs on Linux are not read.
  • Per-process GPU load is read only on Windows.

electron/src/main/secret.test.ts fails on Windows before and after this change: it checks a POSIX file mode.

🤖 Generated with Claude Code

High-level PR Summary

This PR adds a live resource usage panel to the desktop app, showing CPU, RAM, VRAM and GPU utilization for both the machine and SurfSense's share. The panel sits above Studio and displays a per-engine breakdown (llama.cpp, stable-diffusion.cpp, audio.cpp, backend, interface) to help users identify which runtime is holding memory when generation slows. The feature uses platform-specific readers: DXGI and GPU performance counters on Windows, NVML and amdgpu sysfs on Linux, and ioreg on macOS.

⏱️ Estimated Review Time: 30-90 minutes

💡 Review Order Suggestion
Order File Path
1 docs/architecture/resource-usage.md
2 docs/architecture/overview.md
3 surfsense_local/backend/api/config.py
4 surfsense_local/electron/src/main/sidecars/python.ts
5 surfsense_local/electron/src/main/sidecars/python.test.ts
6 surfsense_local/backend/modules/resource_usage/engines.py
7 surfsense_local/backend/modules/resource_usage/parent_map.py
8 surfsense_local/backend/modules/resource_usage/app_tree.py
9 surfsense_local/backend/modules/resource_usage/gpu/carve_out.py
10 surfsense_local/backend/modules/resource_usage/gpu/reading.py
11 surfsense_local/backend/modules/resource_usage/gpu/__init__.py
12 surfsense_local/backend/modules/resource_usage/gpu/windows/adapters.py
13 surfsense_local/backend/modules/resource_usage/gpu/windows/pdh.py
14 surfsense_local/backend/modules/resource_usage/gpu/windows/counters.py
15 surfsense_local/backend/modules/resource_usage/gpu/windows/reader.py
16 surfsense_local/backend/modules/resource_usage/gpu/linux/nvml.py
17 surfsense_local/backend/modules/resource_usage/gpu/linux/amdgpu.py
18 surfsense_local/backend/modules/resource_usage/gpu/linux/reader.py
19 surfsense_local/backend/modules/resource_usage/gpu/darwin/ioreg.py
20 surfsense_local/backend/modules/resource_usage/gpu/darwin/reader.py
21 surfsense_local/backend/modules/resource_usage/snapshot.py
22 surfsense_local/backend/modules/resource_usage/sampler.py
23 surfsense_local/backend/modules/resource_usage/dependencies.py
24 surfsense_local/backend/modules/resource_usage/schemas.py
25 surfsense_local/backend/modules/resource_usage/router.py
26 surfsense_local/backend/api/main.py
27 surfsense_local/frontend/src/features/resources/api.ts
28 surfsense_local/frontend/src/features/resources/breakdown-pref.ts
29 surfsense_local/frontend/src/features/resources/format-usage.ts
30 surfsense_local/frontend/src/features/resources/usage-rows.ts
31 surfsense_local/frontend/src/features/resources/usage-meter.tsx
32 surfsense_local/frontend/src/features/resources/engine-breakdown.tsx
33 surfsense_local/frontend/src/features/resources/use-resource-usage.ts
34 surfsense_local/frontend/src/features/resources/resource-usage-panel.tsx
35 surfsense_local/frontend/src/features/resources/live-resource-usage.tsx
36 surfsense_local/frontend/src/features/dashboard/right-panel.tsx
37 surfsense_local/frontend/src/features/dashboard/dashboard-page.tsx
38 surfsense_local/backend/tests/unit/resource_usage/test_app_tree.py
39 surfsense_local/backend/tests/unit/resource_usage/test_parent_map.py
40 surfsense_local/backend/tests/unit/resource_usage/test_snapshot.py
41 surfsense_local/backend/tests/unit/resource_usage/test_darwin_ioreg.py
42 surfsense_local/backend/tests/unit/resource_usage/test_linux_amdgpu.py
43 surfsense_local/backend/tests/unit/resource_usage/test_windows_counters.py
44 surfsense_local/backend/tests/integration/resource_usage/test_routes.py
45 surfsense_local/frontend/src/features/resources/live-resource-usage.test.tsx
46 surfsense_local/frontend/src/features/resources/resource-usage-panel.test.tsx
47 surfsense_local/frontend/translations/de.json
48 surfsense_local/frontend/translations/en.json
49 surfsense_local/frontend/translations/es.json
50 surfsense_local/frontend/translations/fr.json
51 surfsense_local/frontend/translations/hi.json
52 surfsense_local/frontend/translations/ja.json
53 surfsense_local/frontend/translations/ko.json
54 surfsense_local/frontend/translations/pt-BR.json
55 surfsense_local/frontend/translations/ru.json
56 surfsense_local/frontend/translations/zh-CN.json

Need help? Join our Discord

A Resources panel at the top of the right column shows the machine's CPU,
RAM, VRAM and GPU load, each split into SurfSense's share and other apps,
with a per-engine breakdown for llama.cpp, stable-diffusion.cpp, audio.cpp,
the backend and the interface.

The API samples it at GET /system/usage. Electron passes its pid as
SURFSENSE_LOCAL_SHELL_PID, and every process under it counts as the app,
named by the child of the shell that started its branch. Graphics come
from the OS: GPU performance counters and DXGI on Windows, NVML and amdgpu
sysfs with DRM fdinfo on Linux, ioreg on macOS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
surf-sense-frontend Ready Ready Preview Sep 30, 2026 10:43pm UTC

Request Review

@coderabbitai

coderabbitai Bot commented Sep 30, 2026

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: Repository: MODSetter/SurfSense/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 330404fb-daca-48cd-a80b-691597830721

📥 Commits

Reviewing files that changed from the base of the PR and between c6c84d2 and 54e83a0.

📒 Files selected for processing (62)
  • docs/architecture/overview.md
  • docs/architecture/resource-usage.md
  • surfsense_local/backend/api/config.py
  • surfsense_local/backend/api/main.py
  • surfsense_local/backend/modules/resource_usage/__init__.py
  • surfsense_local/backend/modules/resource_usage/app_tree.py
  • surfsense_local/backend/modules/resource_usage/dependencies.py
  • surfsense_local/backend/modules/resource_usage/engines.py
  • surfsense_local/backend/modules/resource_usage/gpu/__init__.py
  • surfsense_local/backend/modules/resource_usage/gpu/carve_out.py
  • surfsense_local/backend/modules/resource_usage/gpu/darwin/__init__.py
  • surfsense_local/backend/modules/resource_usage/gpu/darwin/ioreg.py
  • surfsense_local/backend/modules/resource_usage/gpu/darwin/reader.py
  • surfsense_local/backend/modules/resource_usage/gpu/linux/__init__.py
  • surfsense_local/backend/modules/resource_usage/gpu/linux/amdgpu.py
  • surfsense_local/backend/modules/resource_usage/gpu/linux/nvml.py
  • surfsense_local/backend/modules/resource_usage/gpu/linux/reader.py
  • surfsense_local/backend/modules/resource_usage/gpu/reading.py
  • surfsense_local/backend/modules/resource_usage/gpu/windows/__init__.py
  • surfsense_local/backend/modules/resource_usage/gpu/windows/adapters.py
  • surfsense_local/backend/modules/resource_usage/gpu/windows/counters.py
  • surfsense_local/backend/modules/resource_usage/gpu/windows/pdh.py
  • surfsense_local/backend/modules/resource_usage/gpu/windows/reader.py
  • surfsense_local/backend/modules/resource_usage/parent_map.py
  • surfsense_local/backend/modules/resource_usage/router.py
  • surfsense_local/backend/modules/resource_usage/sampler.py
  • surfsense_local/backend/modules/resource_usage/schemas.py
  • surfsense_local/backend/modules/resource_usage/snapshot.py
  • surfsense_local/backend/tests/integration/resource_usage/__init__.py
  • surfsense_local/backend/tests/integration/resource_usage/test_routes.py
  • surfsense_local/backend/tests/unit/resource_usage/__init__.py
  • surfsense_local/backend/tests/unit/resource_usage/test_app_tree.py
  • surfsense_local/backend/tests/unit/resource_usage/test_darwin_ioreg.py
  • surfsense_local/backend/tests/unit/resource_usage/test_linux_amdgpu.py
  • surfsense_local/backend/tests/unit/resource_usage/test_parent_map.py
  • surfsense_local/backend/tests/unit/resource_usage/test_snapshot.py
  • surfsense_local/backend/tests/unit/resource_usage/test_windows_counters.py
  • surfsense_local/electron/src/main/sidecars/python.test.ts
  • surfsense_local/electron/src/main/sidecars/python.ts
  • surfsense_local/frontend/src/features/dashboard/dashboard-page.tsx
  • surfsense_local/frontend/src/features/dashboard/right-panel.tsx
  • surfsense_local/frontend/src/features/resources/api.ts
  • surfsense_local/frontend/src/features/resources/breakdown-pref.ts
  • surfsense_local/frontend/src/features/resources/engine-breakdown.tsx
  • surfsense_local/frontend/src/features/resources/format-usage.ts
  • surfsense_local/frontend/src/features/resources/live-resource-usage.test.tsx
  • surfsense_local/frontend/src/features/resources/live-resource-usage.tsx
  • surfsense_local/frontend/src/features/resources/resource-usage-panel.test.tsx
  • surfsense_local/frontend/src/features/resources/resource-usage-panel.tsx
  • surfsense_local/frontend/src/features/resources/usage-meter.tsx
  • surfsense_local/frontend/src/features/resources/usage-rows.ts
  • surfsense_local/frontend/src/features/resources/use-resource-usage.ts
  • surfsense_local/frontend/translations/de.json
  • surfsense_local/frontend/translations/en.json
  • surfsense_local/frontend/translations/es.json
  • surfsense_local/frontend/translations/fr.json
  • surfsense_local/frontend/translations/hi.json
  • surfsense_local/frontend/translations/ja.json
  • surfsense_local/frontend/translations/ko.json
  • surfsense_local/frontend/translations/pt-BR.json
  • surfsense_local/frontend/translations/ru.json
  • surfsense_local/frontend/translations/zh-CN.json
 ______________________________________
< I leave no bug behind. Semper Fixis. >
 --------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@MODSetter
MODSetter merged commit 6860530 into dev Sep 30, 2026
21 of 24 checks passed

This branch was successfully deployed

1 active deployment
Preview — 54e83a08 Deployed Sep 30, 2026 by vercel[bot]
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