Skip to content

Improve macOS GPU monitoring and telemetry - #496

Open
spofdamon wants to merge 13 commits into
Syllo:masterfrom
spofdamon:macos-support
Open

spofdamon wants to merge 13 commits into
Syllo:masterfrom
spofdamon:macos-support

Conversation

@spofdamon

@spofdamon spofdamon commented Aug 5, 2026 •

Copy link
Copy Markdown

Summary

  • make the macOS test suite build reliably, run it in CI, and move platform parsing and sampling logic into focused, testable helpers
  • report per-process GPU utilization from AGX client GPU-time deltas while hardening IOKit and process resource handling
  • correct process CPU accounting under Rosetta and clarify unified-memory reporting
  • add Apple GPU power draw, active-residency-weighted clock speed, GPU temperature, and system fan RPM telemetry, with fractional display for low power values

The Apple-specific telemetry fails gracefully when private IOReport, IOKit, or SMC data is unavailable.

Testing

  • cmake --build build --parallel
  • ctest --test-dir build --output-on-failure
  • 34 of 34 tests pass on an Apple M5 Max running macOS 26.5.2

Apple IOReport samples scale correctly from roughly 1.2 W at idle to more than 60 W under a controlled Metal load. However, integer milliwatt-to-watt conversion flattened the entire 1.0-1.9 W range to 1 W and made the telemetry appear stuck.

Retain one decimal place when no power limit is available and in snapshot output so low-power variation remains visible.
Apple Silicon exposes its GPU thermal domain through undocumented lowercase Tg keys in AppleSMC rather than Metal. Discover that sorted key range with a binary lookup, cache valid float sensors, and report their average without scanning the full SMC table.

Throttle sensor reads to once per second and fail closed when the private protocol, key ordering, types, or permissions differ.
Apple Silicon exposes current fan speeds through undocumented F?Ac AppleSMC keys. Discover and cache valid float sensors alongside the existing GPU temperature keys, throttle samples independently, and report the highest active system fan through nvtop's singular RPM field.

Keep temperature and fan discovery independent so either metric remains available when the other key family is missing or changes. Prefer measured RPM over the integrated-GPU CPU-FAN placeholder, and reject malformed sensor samples.
@spofdamon

spofdamon commented Aug 5, 2026 •

Copy link
Copy Markdown
Author

I can remove 629ab90 if you're not interested in mac CI.

Conflict resolution after the upstream interface/NVLink/ECC refactor:

- interface.c: keep master's NVLink-aware fan layout, but keep this PR's
  fan_rpm-before-CPU-FAN ordering so Apple's SMC tachometer wins over the
  generic "CPU-FAN" placeholder. Keep master's half-watt power formatting.
- tests/CMakeLists.txt: keep master's platform selection for the process
  info source and add the appleTests target from this PR.
- compile.yml: drop the standalone build-macos job; master already builds
  and tests on macOS in the matrix, with SHA-pinned actions.
- Enable IOReport/AppleSMC telemetry only on Apple Silicon. Both private
  interfaces, their key sets and the SMC float encoding are arm64
  specific; Intel Macs also report hasUnifiedMemory for their iGPU.
  Detect with hw.optional.arm64, keeping Rosetta-translated builds
  working (falling back to sysctl.proc_translated).
- Document that IOReportCopyChannelsInGroup's three trailing arguments
  are all uint64_t and match the private ABI, and align the declared
  prototypes (CFMutableDictionaryRef return, int32_t indices/returns).
- Document that AppUsage.accumulatedGPUTime is a nanosecond counter
  (same source as Activity Monitor) and that GPU time can exceed wall
  time before the 100% clamp.
- Document why the SMC result byte is checked and status is not, that
  SMC 'flt' keys are little-endian on Apple Silicon, and that the
  reported fan RPM is the chassis fan shared by the SoC.
- Note the Rosetta 125/3 ns timebase workaround and its htop origin,
  and that the cached timebase is single-threaded.
- Add a README note that power/clock/temperature/fan come from private
  interfaces that may change between macOS releases.
- Report power in whole watts in the TUI and snapshot for every backend,
  including drivers that expose milliwatt precision; drop the fractional
  display proposed by the PR.
- Prefer a real fan RPM over the generic CPU-FAN placeholder
  consistently in the TUI and snapshot output.
- Add tests for a zero timebase denominator and for growing the process
  array across realloc increments.
- Apply clang-format to the new C sources.
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.

2 participants