open-standards/jcp/jcp-rs/crates
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Transaction Science a625a7d70c jcp-energy: the GPU rail's period was wrong by two orders, in the unsafe direction
I declared the Apple `GPU Energy` rail's update period as 10 ms yesterday
(ed00cab1) on the strength of "~10 ms refresh on the parts measured here". That
was an assumption dressed as an observation, and it is wrong the dangerous way:
too short a declared period lets `may_grade_span` grade a span the counter
never covered, and a span landing entirely inside one hold reads **zero** and
would have been graded as a measurement of zero.

Measured properly, sampling every 2 ms on an M5 Max, the gap between actual
changes in the rail:

| condition | p50 | p90 | max | median step |
|---|---:|---:|---:|---:|
| idle | 12.7 ms | 91.0 ms | **992.2 ms** | 1.06 mJ |
| sustained MLX matmul | 13.1 ms | 15.0 ms | 42.0 ms | 73.50 mJ |

The rail has no fixed period. It republishes when there is activity to report
and holds when there is not, so the tight figure is only available to a
measurer who can guarantee the fabric stays busy — and a measurer cannot.
**Declared 1 s**, the idle worst case, because that is the condition a short
span is most likely to fall inside.

This also reconciles a fleet note that put the hold at "300–600 ms under load",
measured from a GGUF decode. That decode is dispatch-bound with idle gaps
between tokens, so it was sampling the idle behaviour rather than the loaded
one; under genuinely sustained load the rail is tight (max 42 ms). The two
observations agree once the cause is named, and the cause is what decides which
number to declare.

The headline figure survives, for the reason it was taken that way: the Laya
GPU span was 2.606 s, above even the idle worst case. A single 11.85 ms
decision could never have been one counter read, which is pinned in the test
alongside the 42 ms and 992 ms refusals so the period cannot drift back.

**Also corrects an overclaim in ed00cab1's message**, which said this "stop[s]
metering the Neural Engine as free". The code change there was right — count
the `ANE Energy` aggregate where a part publishes one, else the per-engine
rails — but on this hardware it changes nothing, because `ANE0` is frozen for
an unprivileged reader. The survey already reported `npu/ioreport` as `Frozen`;
it now also records the only route that exists: `sudo powermetrics --samplers
ane_power`, machine-wide, `NeedsPrivilege`. ANE work runs in `aned`, so it is
not this process's CPU energy either, and the load-balancer clients carry no
statistics — a span that used the ANE is CPU+GPU only and Partial.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-10-05 07:20:58 -04:00
..
jcp-a2a jcp: caveats — the open attenuation axis (SPEC §4.9, C24) 2026-07-19 11:03:04 -04:00
jcp-action-receipt jcp-gateway: the plaintext figure beside a receipt says whether it is a reading 2026-09-30 20:09:50 -04:00
jcp-bridge jcp-bridge: Identify the authorization server per RFC 9207 2026-07-21 06:32:50 -04:00
jcp-channel jcp: caveats — the open attenuation axis (SPEC §4.9, C24) 2026-07-19 11:03:04 -04:00
jcp-cite jcp-cite: tighten unreadable_by — real authorization via a caller predicate 2026-07-20 19:10:48 -04:00
jcp-cli jcp: caveats — the open attenuation axis (SPEC §4.9, C24) 2026-07-19 11:03:04 -04:00
jcp-conformance jcp: read the three pack files nothing read 2026-09-26 05:21:54 -04:00
jcp-efficiency jcp: a live vendor counter is a reading; intercept/1 keeps a partial figure partial 2026-09-30 20:06:16 -04:00
jcp-energy jcp-energy: the GPU rail's period was wrong by two orders, in the unsafe direction 2026-10-05 07:20:58 -04:00
jcp-flow jcp-flow: Compute propagated provenance from tool bytes 2026-07-22 02:09:29 -04:00
jcp-gateway jcp-gateway, joule-ui-serve: name the plaintext figure cost_uj 2026-10-01 01:26:57 -04:00
jcp-grant jcp: caveats — the open attenuation axis (SPEC §4.9, C24) 2026-07-19 11:03:04 -04:00
jcp-intercept jcp: a live vendor counter is a reading; intercept/1 keeps a partial figure partial 2026-09-30 20:06:16 -04:00
jcp-orchestrate jcp: caveats — the open attenuation axis (SPEC §4.9, C24) 2026-07-19 11:03:04 -04:00
jcp-policy jcp-policy: contextual service policies (content-keyed + require-approval) 2026-06-27 18:58:55 -04:00
jcp-prompt jcp-prompt: a signed, content-addressed prompt registry 2026-06-27 19:57:46 -04:00
jcp-receipt jcp: an erasure path that neither breaks the chain nor loses the joules 2026-09-03 15:15:51 -04:00
jcp-runtime jcp-runtime: Gate a call on its argument's propagated provenance 2026-07-22 04:03:15 -04:00
jcp-schema jcp: a live vendor counter is a reading; intercept/1 keeps a partial figure partial 2026-09-30 20:06:16 -04:00
jcp-threshold jcp: caveats — the open attenuation axis (SPEC §4.9, C24) 2026-07-19 11:03:04 -04:00
jcp-trace jcp-trace: a std-only OTLP /v1/traces receiver (server feature) 2026-06-27 20:53:48 -04:00
jcp-wire jcp: caveats — the open attenuation axis (SPEC §4.9, C24) 2026-07-19 11:03:04 -04:00
jcp-x402 jcp: caveats — the open attenuation axis (SPEC §4.9, C24) 2026-07-19 11:03:04 -04:00