jouleclaw-energy: a Mac's whole-machine power from the SMC (EnergyDomain::System, ModelBased) #622
Merged
dcharlot
merged 1 commit from 2026-11-05 04:30:59 -05:00
jouleclaw-energy/smc-system into main 2026-11-04
jouleclaw-energy: a Mac's whole-machine power from the SMC (EnergyDomain::System, ModelBased)
All checks were successful
standards workspaces build + test / joulespec-proofs (joulespec/joulespec-rs, joulespec-proofs, true, macos) (pull_request) Successful in 2m9s
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Successful in 2m9s
standards workspaces build + test / joule-ui-rs (joule-ui/joule-ui-rs, joule-ui-rs, linux) (pull_request) Successful in 1m18s
energy meters on real hardware / sink decode table · RAPL on jetson-hub (NVML surveyed) (pull_request) Successful in 3m1s
standards workspaces build + test / jcp-rs (jcp-conformance, jcp/jcp-rs, -p jcp-energy --features nvml, jcp-rs, linux) (pull_request) Successful in 2m4s
standards workspaces build + test / joulehook-rs (joulehook/joulehook-rs, joulehook-rs, linux) (pull_request) Successful in 57s
standards workspaces build + test / pool-rs (pool/pool-rs, pool-rs, linux) (pull_request) Successful in 59s
wai-quantum WebGPU member / member · browser WebGPU (macos) (pull_request) Successful in 1m23s
standards workspaces build + test / sense-rs (sense/sense-rs, sense-rs, linux) (pull_request) Successful in 48s
standards workspaces build + test / proof-rs (proof/conformance/v1/joulespec.toml, proof-conformance, proof/proof-rs, proof-rs, linux, true) (pull_request) Successful in 1m4s
wai-quantum WebGPU member / member · Metal (macos) (pull_request) Successful in 3m8s
standards workspaces build + test / eoc-rs (eoc/eoc-rs, -p eoc-meter --features cuda, eoc-rs, linux) (pull_request) Successful in 4m40s
wai-quantum WebGPU member / member · software Vulkan (linux) (pull_request) Successful in 1m42s
standards workspaces build + test / joulespec-rs (true, joulespec/joulespec-rs, true, joulespec-rs, linux) (pull_request) Successful in 2m30s
standards workspaces build + test / smart-byte-rs (smart-byte/smart-byte-rs, smart-byte-rs, linux) (pull_request) Successful in 4m25s
standards workspaces build + test / sandbox-rs (sandbox-conformance, sandbox/sandbox-rs, -p sandbox-tee --features amd-kds,intel-pcs, sandbox-rs, linux) (pull_request) Successful in 5m19s
wai-quantum WebGPU member / shader checks · browser build · wasip2 inertness (pull_request) Successful in 6m30s
wai-quantum WebGPU member / member · DX12 and Vulkan (cbio-windows) (pull_request) Successful in 11m38s
wai-quantum WebGPU member / member · integrated GPU, Vulkan (framework-128gb) (pull_request) Successful in 10m56s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 11m21s
wai-quantum WebGPU member / member · GPU, Vulkan (jetson-hub) (pull_request) Successful in 17m37s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 1m13s
standards workspaces build + test / joulecontract-rs (joulecontract/joulecontract-rs, joulecontract-rs, linux-arm64, true) (pull_request) Successful in 1m3s
standards workspaces build + test / mesh-rs (mesh/mesh-rs, -p mesh-engine-gguf -p mesh-openai --features mesh-engine-gguf/gguf,mesh-openai/server, mesh-rs, linux-arm64) (pull_request) Successful in 1m1s
standards workspaces build + test / map-rs (map-conformance, map/map-rs, map-rs, linux-arm64) (pull_request) Successful in 1m45s
standards workspaces build + test / jouleclaw-rs (-nodebug, jouleclaw/jouleclaw-rs, -p jouleclaw-energy --features rapl,nvml, jouleclaw-rs, linux-arm64, -C target-feature=+fp16) (pull_request) Successful in 3m32s
wai-quantum WebGPU member / member · GPU, Vulkan (thor) (pull_request) Successful in 24m45s
standards workspaces build + test / aac-rs (aac-conformance, aac/aac-rs, aac-rs, linux-arm64) (pull_request) Successful in 5m35s
standards workspaces build + test / openpay (openpay, openpay, linux-arm64) (pull_request) Successful in 4m5s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 6m38s
On Apple Silicon under macOS 27, IOReport's CPU rails are frozen for an unprivileged reader, so detect_meter fell back to the load-average estimator: a guess, graded Estimator. Every Mac still publishes its total power in the SMC key PSTR, which any process reads through the AppleSMCKeysEndpoint IOKit user client with no root. New feature `smc` (macOS), module apple_smc: SmcSystemCounter integrates PSTR over time. - Domain: a new EnergyDomain::System, the whole machine (everything its DC input feeds: SoC, memory, storage, fans, the rest of the board; not the power supply's AC-to-DC loss). It holds SocTotal and every other domain. - Grade: ModelBased, like NVML's power.draw integral. PSTR is a power reading, not an energy counter, so no liveness probe can vouch for its integral. - Sampling: one thread per process reads PSTR every 100 ms and integrates the value it holds, so a figure does not depend on how often its caller reads; a read between polls extends the integral at the held value, which the next poll integrates over the same time, so readings never run backwards. - Checks: PSTR must be a 4-byte float and be seen to refresh before the counter is available (the first construction waits about a second); samples at 0 W or less, above 1.5 kW, or NaN are discarded and counted; a value held 10 s gives no figure. - Minimum window 2 s: PSTR refreshes about once a second (median gap 1.0 s on an M3 Ultra Mac Studio and an M5 Max MacBook Pro, macOS 27.2) and trails a step in load by about one refresh. detect_meter puts it after a live IOReport counter (a hardware reading over a narrower domain) and before the load-average estimator. Its figure holds the work and whatever else the machine powered, so it can read high, never low. mesh-meter's exhaustive covers_whole_request counts System as covering the whole request. SPEC 1.3 lists sampled vendor power integrated over time under ModelBased. Measured with the energy_probe example (2.5 s CPU churn, unprivileged): the M3 Ultra Mac Studio 299.9 J, 120.0 W; the M5 Max MacBook Pro on AC 160.9 J, 64.4 W. On the Studio PSTR equals the DC input (PDTR); on the MacBook Pro, on AC with the battery not charging, it read 51.7 W against 54.9 W at the input. Tests: the integral, monotonic reads, implausible samples, staleness and the sampler's start are driven with scripted samples and times; a hardware test meters a CPU burn from the real SMC and prints "apple-smc: measured", which a new macOS CI step greps under --features smc and ioreport,smc. The clippy step lints both. Passing on the M3 Ultra (smc, ioreport,smc, ioreport; clippy clean in default, ioreport, smc, ioreport,smc; mesh-meter with hw-meter-apple) and on Linux x86_64 (rapl,nvml; default clippy; mesh-meter with hw-meter-rapl). Co-Authored-By: Claude Opus 5.5 <[email protected]>