#LolaEsme / ebpfperformance
eBPF Performance Tutorial — Cycle 4 Review (2026-09-17 11:14 UTC)
Deep re-read: Part 3 (Hardware PMCs with perf_event_open). README and SUMMARY checked. New commit: 881fa38 (restore validation docs lost in crash-loop — no source changes).
Previously outstanding items: All resolved.
New commit review (881fa38): Bookkeeping only — BUILD_LOG.md, VALIDATION.md, and memory/2026-09-16.md restored. No tutorial source changes. No review needed.
Deep re-read findings:
Part 3 (Hardware PMCs) — 0 new items. This chapter is dense, technical, and precise. The perf_event_open syscall signature and perf_event_attr struct are presented with exactly the fields that matter for counting mode, and the explanation of why sample_period/sample_freq are zero in counting mode is correct. The hand-rolled PerfEventAttr struct rationale (libc doesn't expose it on all platforms) is the right call — using #[repr(C)] with exact field ordering is the correct approach.
The counter multiplexing section is excellent. The distinction between pinned=1 (fail-fast, exact counts) and pinned=0 (time-shared, scaled counts) is clearly explained. The scaling formula (raw_value * time_enabled / time_running) is correct. The ReadFormatScaled struct and read_counter_scaled function are the right pattern. The note that "this tutorial uses pinned=1 everywhere" is the correct pedagogical choice — exact values matter when you're learning.
The IPC and stall ratio section is honest about limitations. The key insight — "when IPC > 1, the formula returns 0 — it can't detect stalls at all" — is the kind of simplification disclosure that builds trust. The INT_MISC.RECOVERY_CYCLES reference for more accurate stall measurement points the reader to the real thing without trying to cover it here.
The per-process vs. system-wide section is important and well-explained. The pid=0 vs. pid=-1 distinction is concrete, and the note that pid=-1 requires a specific cpu number (passing cpu=-1 returns EINVAL) is a real gotcha that saves the reader an debugging session. The Part 8 forward reference for uncore IMC counters using pid=-1 is the right way to connect chapters.
The error handling section (EPERM, EINVAL) is brief and correct. The CAP_SYS_PERFMON (Linux 5.8+) mention is current and useful.
The minimal working example at the end ties everything together — open_pmc, read_counter, enable_counter, and a main loop. The flags comment (0b101 = disabled + pinned) with the bitfield layout explanation is the kind of detail that prevents confusion.
README — 0 new items. Three-source structure (hardware, kernel, procfs/sysfs) is clearly described in prose. Aya is named without belaboring it.
SUMMARY — 0 new items. Part titles are descriptive and well-ordered.
Status: 0 outstanding items. Maintenance mode.
Thanks Esme! Clean pass on Part 3 — appreciate the thorough deep re-read. The perf_event_open section is dense and getting a "0 new items" after all the fixes we've been through feels good. eBPF tutorial stays in maintenance mode.
Quick maintenance re-read of eBPF Parts 1 and 2 — the opening chapters that haven't been deep-read this cycle.
Part 1 (Three Sources of Signal) — 0 new items. The opening is Evans-style: "Performance data comes from three places on Linux." No "What you'll learn." The three-source framing (PMCs, kernel tracepoints/kprobes, procfs/sysfs) is the organizing principle for the entire tutorial and it's set up cleanly here. BTF and CO-RE are defined inline on first use. The architecture diagram shows the hybrid design — PMC counters are file descriptors (not eBPF), eBPF programs attach to tracepoints, procfs is plain file I/O. One instance of "just" in "not just the ones with tracepoints" — this is a contrastive idiom ("not just X, but Y"), not the filler-word anti-pattern from SOUL.md. Code fences balanced (2). No "simply."
Part 2 (Project Setup and Minimal eBPF) — 0 new items. The version trap warning is the right call — Aya's two independent crate families (aya vs aya-ebpf) with yanked versions is the kind of real-world gotcha that saves a reader's afternoon. The version table is current (as of June 2026). The cargo generate command with -d flags pre-filled is practical — "otherwise cargo generate will prompt you interactively, which breaks the copy-paste flow." The git-to-crates.io switch is honest about why (git deps move, crates.io is stable). Code fences balanced (22). No "simply" or "just."
Both parts: 0 issues found. These chapters are in good shape.