From 5dcd5719841980ee0361a9d5bb5fa3456db4b083 Mon Sep 17 00:00:00 2001 From: diego Date: Sat, 17 Oct 2026 12:32:36 -0300 Subject: [PATCH] docs: drop closed-issue citations, and credit parcagpu in one place MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two unrelated things a reader notices and a writer does not. ISSUE NUMBERS. The user docs cited eight issues; six were closed, so clicking one landed on resolved work explaining nothing the paragraph had not already said. Citing an issue is useful when the reader can act on it — an open limitation they might hit — and is archaeology otherwise. The closed ones are gone from docs/, examples/ and the README; #194 stays in both places it appears, because it is open and names a limit a reader will meet. The CHANGELOG keeps all of its references: that is the historical record, where the numbers belong. One of those was not archaeology but a live falsehood #209 missed. The examples table still read "Not runnable yet — see #121" for kubernetes/, while the prose three lines below already said the opposite. Fixing the prose and leaving the table is how a document ends up contradicting itself in the same screen. PARCAGPU. The injection pattern is theirs and we took it directly, so the credit stays — but it opened the section meant to explain OUR two deployments, and their name appeared three times before a reader learned how to use either of ours. That reads as a comparison piece rather than a how-to, and it buries the attribution in argument rather than stating it. It is now a short "Prior art" section of its own, before anything else: the pattern is theirs, we took it directly, this document is what we do inside it. The privilege comparison keeps every number it had and moves under a heading that says what it is for, at the end of the deployments section instead of interleaved with them. No claim changed. "Neither deployment is zero-touch", including the note that Parca is in the same position, stays exactly where it was. --- docs/cpython-frame-walking.md | 4 ++-- docs/debuginfod-symbolization.md | 2 +- examples/README.md | 13 +++---------- examples/kubernetes/README.md | 21 ++++++++++++++------- examples/rust-pgo/README.md | 2 -- 5 files changed, 20 insertions(+), 22 deletions(-) diff --git a/docs/cpython-frame-walking.md b/docs/cpython-frame-walking.md index 5003da4..06246b4 100644 --- a/docs/cpython-frame-walking.md +++ b/docs/cpython-frame-walking.md @@ -1,6 +1,6 @@ # Reading CPython's frame chain from outside the process -Notes gathered while building the BPF-side Python unwinder (issue #83). +Notes gathered while building the BPF-side Python unwinder. Everything here was checked against CPython source and, where a number is quoted, measured against real interpreter binaries on this host. It is written down because most of it is not in any CPython document, and three @@ -11,7 +11,7 @@ Supported range is CPython 3.12, 3.13 and 3.14, on amd64 and arm64, glibc only. Each architecture carries its own measured glibc pthread-TSD offsets and its own machine-code shapes for the `autoTSSkey` reference; an architecture with neither is refused by name rather than walked with -guessed values ([#206](https://github.com/dpsoft/perf-agent/issues/206)). +guessed values. --- diff --git a/docs/debuginfod-symbolization.md b/docs/debuginfod-symbolization.md index 0babea0..ff1f245 100644 --- a/docs/debuginfod-symbolization.md +++ b/docs/debuginfod-symbolization.md @@ -213,7 +213,7 @@ fetch. M2 will add an explicit cache-invalidation flag. - **Metrics exporter integration.** Counters exist internally (see `symbolize/debuginfod/stats.go`) and are accessible via the `Stats()` - method and the agent prints them at shutdown (#109), but the snapshot is + method and the agent prints them at shutdown, but the snapshot is still not wired through the `metrics.Exporter` interface. Prometheus/OpenTelemetry export of cache hit rate, fetch latency, and error counts is deferred to M2. diff --git a/examples/README.md b/examples/README.md index 33777cb..a7a0b4d 100644 --- a/examples/README.md +++ b/examples/README.md @@ -10,19 +10,12 @@ own README, source workload, and driver script. | [`rust-pgo/`](rust-pgo/) | Rust AutoFDO PGO. Build → profile → `create_llvm_prof` → rebuild → strip → measure speedup. | | [`cpp-pgo/`](cpp-pgo/) | C++ AutoFDO PGO. Same shape via clang's `-fprofile-sample-use`. | | [`flamegraph/`](flamegraph/) | Render a Brendan-Gregg flame graph from a perf-agent capture. | -| [`kubernetes/`](kubernetes/) | Profile an unmodified PyTorch CUDA pod in k8s via CUPTI injection, as a sidecar. **Not runnable yet — see #121.** | +| [`kubernetes/`](kubernetes/) | Profile an unmodified PyTorch CUDA pod in k8s via CUPTI injection, as a sidecar or a node collector. Needs a cluster with an NVIDIA GPU node. | The first three depend on `perf-agent` being built and on PATH with the standard capability set (`setcap cap_bpf,cap_perfmon,cap_sys_ptrace,cap_checkpoint_restore,cap_syslog+ep`). - -## All of these run today - -`kubernetes/` used to be the exception, because the shim could not load into -the images it would be injected into (#121) and nothing was published to name -in a pod spec (#139). Both are closed, and v1.3.0 publishes -`ghcr.io/dpsoft/perf-agent` and `ghcr.io/dpsoft/perf-agent-shim` as multi-arch -images, so the manifests there pull. What it still needs from you is a -cluster with an NVIDIA GPU node. +`kubernetes/` needs a cluster with an NVIDIA GPU node instead; the images its +manifests name are published, so there is nothing to build for it. ## Why these are here diff --git a/examples/kubernetes/README.md b/examples/kubernetes/README.md index 7c99ece..74c61c9 100644 --- a/examples/kubernetes/README.md +++ b/examples/kubernetes/README.md @@ -21,12 +21,16 @@ flame graph. > **Both images are multi-arch** (amd64 and arm64), built natively on each > architecture rather than under emulation. -## Two deployments: sidecar and collector +## Prior art + +The injection pattern here is not ours. [Polar Signals' `parcagpu`][ps] +established it: an init container drops a CUPTI-based `.so` onto a shared +volume, and the application container loads it through +`CUDA_INJECTION64_PATH`. We took that directly, and the rest of this document +is what we do inside it rather than a claim to have invented it. Where the +two differ is privilege, compared below. -[Polar Signals' `parcagpu`][ps] established the injection pattern both of ours -follow: an init container drops a CUPTI-based `.so` onto a shared volume, and -the application container loads it via `CUDA_INJECTION64_PATH`. That part we -take directly. +## Two deployments: sidecar and collector There are two manifests here, and the difference is **where the agent runs**, which decides **how many shim inodes exist**: @@ -48,7 +52,10 @@ we noticed it. One inode per node removes all three — measured on an RTX 3090, with rediscovery disabled, was sampled anyway; a byte-identical copy at another path was not. -Against parcagpu, the difference that survives is privilege, not topology: +### What differs from parcagpu + +Topology aside, one difference is worth stating because it is the reason to +prefer this shape: | | parcagpu | perf-agent collector | |---|---|---| @@ -121,7 +128,7 @@ Brendan Gregg toolchain path. ### Reading the result without being misled A GPU flame graph is not a CPU flame graph with extra frames, and three of its -properties will mislead a reader who assumes otherwise (issue #123): +properties will mislead a reader who assumes otherwise: - **A CPU frame under `[gpu:launch]` is as wide as the GPU time launched *from* it** — not the CPU time spent in it. The Python and C++ frames you recognize diff --git a/examples/rust-pgo/README.md b/examples/rust-pgo/README.md index 1328943..a0fa26a 100644 --- a/examples/rust-pgo/README.md +++ b/examples/rust-pgo/README.md @@ -91,8 +91,6 @@ rustc beating clang — the two examples' workloads and iteration counts differ, and neither is a benchmark. Both exist to show that perf-agent's output drives the AutoFDO toolchain. -See [#168](https://github.com/dpsoft/perf-agent/issues/168). - ## Why this works The dispatch loop hits the `Add` arm 99% of the time. Without PGO, the