Skip to content

Release the shared kernel BTF cache after Start() - #283

Merged
gh-worker-dd-mergequeue-cf854d[bot] merged 1 commit into
mainfrom
mbertrone/release-btf-cache-after-start
Aug 4, 2026
Merged

Release the shared kernel BTF cache after Start()#283
gh-worker-dd-mergequeue-cf854d[bot] merged 1 commit into
mainfrom
mbertrone/release-btf-cache-after-start

Conversation

@mbertrone

Copy link
Copy Markdown
Contributor

What

Manager.Start() already releases VerifierOptions.Programs.KernelTypes once program loading is done (unless KeepKernelBTF is set), but it never released VerifierOptions.Cache — the shared *btf.Cache introduced with the cilium/ebpf v0.22.0 upgrade. A long-lived manager therefore keeps that cache, and the parsed kernel vmlinux BTF it holds, pinned for the entire process lifetime, regressing idle memory for downstream consumers.

This clears VerifierOptions.Cache symmetrically with KernelTypes, via a small releaseKernelBTF() helper.

Why it's safe

  • VerifierOptions.Cache is only consumed while loading the collection (loadCollectionebpf.NewCollectionWithOptions), which runs during InitWithOptions/postInit, strictly before Start().
  • Nothing reads .Cache after Start(). The only post-Start program load, CloneProgram, goes through the exported ebpf.NewProgramWithOptions, which allocates its own fresh btf.NewCache() and relies on KernelTypes (not .Cache) for CO-RE relocations — which is why the clear stays gated on !KeepKernelBTF.

Why it's sufficient

The loaded ebpf.Collection/ebpf.Program don't retain the cache (a Program keeps only its own btf.Handle); the *btf.Cache otherwise lives only in the transient collection loader. So the manager's VerifierOptions.Cache field is the only long-lived reference — clearing it lets the parsed kernel BTF become GC-eligible.

Test

TestReleaseKernelBTF (table-driven, no kernel/root needed) covers both paths: released when !KeepKernelBTF, retained when set. gofmt and go vet clean.

🤖 Generated with Claude Code

Manager.Start() releases VerifierOptions.Programs.KernelTypes once loading is done (unless KeepKernelBTF is set), but it did not release VerifierOptions.Cache, which was added alongside the cilium/ebpf v0.22.0 upgrade. A long-lived manager therefore keeps the shared *btf.Cache -- and the parsed kernel vmlinux BTF it holds -- pinned for the entire process lifetime, regressing idle memory for downstream consumers.

Clear VerifierOptions.Cache symmetrically with KernelTypes, extracted into a small releaseKernelBTF helper. The cache is only consumed while loading the collection (before Start); nothing reads it afterwards: CloneProgram reloads through the exported NewProgramWithOptions, which allocates its own fresh cache and relies on KernelTypes for CO-RE relocations. Gated on KeepKernelBTF so callers that clone programs are unaffected.

Add TestReleaseKernelBTF covering both the release and retain paths.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mbertrone added a commit to DataDog/datadog-agent that referenced this pull request Jul 23, 2026
Pin DataDog/ebpf-manager to the commit that clears the shared BTF cache and
KernelTypes spec in Manager.Start() once program loading finishes, so a
long-lived system-probe no longer keeps the parsed kernel vmlinux BTF pinned
for the whole process lifetime (idle-memory regression).

Temporary pseudo-version pending the v0.8.1 tag; see DataDog/ebpf-manager#283.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
gh-worker-dd-mergequeue-cf854d Bot pushed a commit to DataDog/datadog-agent that referenced this pull request Jul 27, 2026
)

### What does this PR do?

Bumps `github.com/DataDog/ebpf-manager` to the commit that releases kernel BTF once eBPF program loading finishes. `Manager.Start()` now clears both `VerifierOptions.Programs.KernelTypes` and the shared `VerifierOptions.Cache` after the collection is loaded (unless the caller opts out via `KeepKernelBTF`).

Pinned as a temporary pseudo-version (`v0.8.1-0.20260723114030-df952c39a4e3`) pending the `v0.8.1` tag — see DataDog/ebpf-manager#283.

### Motivation

A long-lived `system-probe` kept the parsed kernel vmlinux BTF pinned in the shared verifier cache for the entire process lifetime, even though it is only needed while loading programs. This regressed idle heap/RSS. Releasing the cache after load lets that memory be reclaimed.

### Describe how you validated your changes

- Upstream change carries a unit test (`TestReleaseKernelBTF`) covering both the default-release and `KeepKernelBTF`-retain paths.
- Built `system-probe` against the pinned version and confirmed it compiles and loads eBPF programs (NPM + USM + CWS) without errors.

### Additional Notes

Follow-up: once DataDog/ebpf-manager#283 merges and `v0.8.1` is tagged, swap the pseudo-version for the tag and re-run `dda inv tidy`.


Co-authored-by: matteo.bertrone <matteo.bertrone@datadoghq.com>
@mbertrone
mbertrone marked this pull request as ready for review August 3, 2026 14:38
@mbertrone
mbertrone requested a review from a team as a code owner August 3, 2026 14:39
@gh-worker-dd-mergequeue-cf854d
gh-worker-dd-mergequeue-cf854d Bot merged commit f6fd2cc into main Aug 4, 2026
4 checks passed
@gh-worker-dd-mergequeue-cf854d
gh-worker-dd-mergequeue-cf854d Bot deleted the mbertrone/release-btf-cache-after-start branch August 4, 2026 10:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants