Skip to content

Fix kperf hardware-counter sampling on Apple Silicon - #5

Closed
StefanoD wants to merge 1 commit into
D-Berg:mainfrom
StefanoD:fix-kperf-apple-silicon-sampling
Closed

Fix kperf hardware-counter sampling on Apple Silicon#5
StefanoD wants to merge 1 commit into
D-Berg:mainfrom
StefanoD:fix-kperf-apple-silicon-sampling

Conversation

@StefanoD

@StefanoD StefanoD commented Jul 12, 2026

Copy link
Copy Markdown

Fixes #4.

Summary

sudo crap panicked 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 name

startSampling looked events up by the KpepEventAlias enum tag ("Cycles", "Instructions") instead of the real PMC event names. The kpep database indexes events as FIXED_CYCLES, FIXED_INSTRUCTIONS, … — the exact names already listed in KpepEventAlias.getNames(), which was defined but never called. The fix consults getNames() and tries each candidate name.

thread panic: unable to start kperf sampling: EventNotFound
src/kperf.zig:366  return xnu.Error.EventNotFound

2. integer overflow — non-monotonic per-thread counters

Summing per-thread deltas did counters_1 - counters_0 as a plain u64 subtraction. 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. Extracted addSaturatingDiffs(), which saturates so such a thread contributes 0.

thread panic: integer overflow
src/kperf.zig:286  counter_diffs[i] += t_data.counters_1[i] - t_data.counters_0[i]

Tests

Adds a zig build test step and unit tests for both fixes:

  • addSaturatingDiffs saturates 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.zig behind a comptime macOS guard — discovered on the macOS target and pruned on Linux/Windows (the executable still cross-compiles unchanged). CI currently runs zig build release only; on the macos-latest runner a zig build test step would exercise these.

Verified

M2 (Darwin 25.5). Before: panic (both, sequentially). After: sudo crap reports counters — e.g. an AES-256-GCM 1200 B seal+open micro-benchmark, RustCrypto software vs ring:

Benchmark 1  rustcrypto:  cpu_cycles 268M    instructions 147M
Benchmark 3  ring:        cpu_cycles 9.50M   instructions 5.94M   ⚡ -96.5%
  • zig build test → 3 pass (verified failing when an assertion is broken).
  • zig build and zig build -Dtarget=x86_64-linux unchanged.

🤖 Generated with Claude Code

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>
@StefanoD
StefanoD force-pushed the fix-kperf-apple-silicon-sampling branch from 0c5263b to 14fa9ed Compare July 12, 2026 13:50
@D-Berg D-Berg closed this Jul 14, 2026
@StefanoD

Copy link
Copy Markdown
Author

Sad, that you didn't left any comments what's wrong with the PR and closed it without any comments...
I'm also not sure that your PR addresses also the integer-underflow which showed up in the debug build.

@D-Berg

D-Berg commented Jul 14, 2026

Copy link
Copy Markdown
Owner

Sorry but I thought the pr was AI generated and therefore saw no reason to take my time to respond to it.

@StefanoD

Copy link
Copy Markdown
Author

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.
I use AI professionally in my company and honestly, I don't share the anti AI campaign from different people which close PRs with real fixes, without further comments or having a deeper look in the PR.
I mean, just read blog posts like this here to let you open the eyes that you shouldn't just simply dismiss something, because it is from AI.

@D-Berg

D-Berg commented Jul 14, 2026

Copy link
Copy Markdown
Owner

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.

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.

Crap fails to run under sudo on macOS 26

2 participants