Fix kperf hardware-counter sampling on Apple Silicon - #5
Conversation
Fixes D-Berg#4. `sudo crap` panicked on Apple Silicon (M2) before reporting any hardware counters. Two independent bugs in the kperf path: 1. Event lookup used the wrong name. The lookup passed the KpepEventAlias enum tag ("Cycles"/"Instructions") to kpep_db_event(), but the kpep database indexes events by their PMC names ("FIXED_CYCLES", "FIXED_INSTRUCTIONS", ...). The correct names were already listed in the never-called KpepEventAlias.getNames(); consult it and try each candidate. thread panic: unable to start kperf sampling: EventNotFound kperf.zig:366 ... return xnu.Error.EventNotFound 2. Counter-diff underflow. Summing per-thread deltas computed counters_1 - counters_0 as a plain u64 subtraction. Per-thread PMC snapshots are normally monotonic, but on asymmetric P/E cores a thread's accumulated counter can read lower on a later sample (counter virtualization), underflowing the subtraction. Extract addSaturatingDiffs() and saturate so such a thread contributes 0. thread panic: integer overflow kperf.zig:286 ... counter_diffs[i] += t_data.counters_1[i] - t_data.counters_0[i] Add a `zig build test` step and unit tests for both fixes (the saturating diff helper, and that getNames() yields real PMC event names). The kperf code is macOS-only, so the tests are discovered on the macOS target and pruned elsewhere; the executable still cross-compiles to Linux/Windows unchanged. Tested on an M2 (Darwin 25.5): `sudo crap` now reports cpu_cycles / instructions instead of panicking. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
0c5263b to
14fa9ed
Compare
|
Sad, that you didn't left any comments what's wrong with the PR and closed it without any comments... |
|
Sorry but I thought the pr was AI generated and therefore saw no reason to take my time to respond to it. |
|
Not sure I can follow your reasoning. The fix is from AI, also the text, but I (a human) filed the PR. And since it fixed the bug on my machine, I thought it was worth it, sharing it. |
|
Yeah AI is cool and all but if it’s AI generated I see no reason or obligation to respond with my reason for closing it. If a human takes their time to craft a message I will take my time to craft a response. I do not share that sentiment for bots…. This is just a hobby fork, feel free to fork it as well. |
Fixes #4.
Summary
sudo crappanicked on Apple Silicon (M2) before printing any hardware counters. Two independent bugs in the kperf path, plus tests. (#4 reports the first panic on macOS 26; the second surfaces once that's fixed.)1.
EventNotFound— event lookup used the wrong namestartSamplinglooked events up by theKpepEventAliasenum tag ("Cycles","Instructions") instead of the real PMC event names. The kpep database indexes events asFIXED_CYCLES,FIXED_INSTRUCTIONS, … — the exact names already listed inKpepEventAlias.getNames(), which was defined but never called. The fix consultsgetNames()and tries each candidate name.2.
integer overflow— non-monotonic per-thread countersSumming per-thread deltas did
counters_1 - counters_0as a plainu64subtraction. Per-thread PMC snapshots are normally monotonic, but on Apple Silicon's asymmetric P/E cores a thread's accumulated counter can read lower on a later sample (counter virtualization across core types), underflowing the subtraction — a panic in Debug, a garbage wrap in ReleaseFast. ExtractedaddSaturatingDiffs(), which saturates so such a thread contributes0.Tests
Adds a
zig build teststep and unit tests for both fixes:addSaturatingDiffssaturates a backwards counter instead of underflowing.KpepEventAlias.getNames()yields the real PMC event names (FIXED_CYCLES, …), guarding the data the lookup now depends on.The kperf code is macOS-only, so the tests are referenced from
main.zigbehind acomptimemacOS guard — discovered on the macOS target and pruned on Linux/Windows (the executable still cross-compiles unchanged). CI currently runszig build releaseonly; on themacos-latestrunner azig build teststep would exercise these.Verified
M2 (Darwin 25.5). Before: panic (both, sequentially). After:
sudo crapreports counters — e.g. an AES-256-GCM 1200 B seal+open micro-benchmark, RustCrypto software vsring:zig build test→ 3 pass (verified failing when an assertion is broken).zig buildandzig build -Dtarget=x86_64-linuxunchanged.🤖 Generated with Claude Code