feat(memtrack): capture allocation stacks in eBPF - #522
Draft
not-matthias wants to merge 16 commits into
Draft
Conversation
Copy the caller's user stack in chunks at allocator entry and fold an FNV-1a digest over it in the kernel. The digest rides on the allocation event as stack_hash; the copied bytes, a DWARF-numbered register snapshot and a frame-pointer walk are emitted once per distinct digest on a dedicated ring buffer, so unwinding and symbolication can happen offline. Capture stays off until userspace sets the rodata toggle, so allocator probes are unchanged by default. Refs COD-3222
Add the userspace half of allocation stack capture: env-driven configuration, stack-definition ring parsing, loss counters, per-pid module mapping tracking, a folding recorder that deduplicates definitions and counts occurrences, and the report it produces. Nothing constructs these yet; the tracker wiring follows. Refs COD-3222
Wire the capture rodata and map sizing into skeleton load, poll the stack-definition ring alongside the event ring, and expose the loss counters and frame-pointer chains. The attach worker snapshots module mappings while it holds a process stopped, which is the only point they are guaranteed readable. Guard the lifecycle: finishing with a live session would block forever on the recorder, and a second spawn would leave the capture rings undrained, so both now fail with a descriptive error. With capture disabled the ring buffer and frame-pointer map shrink to the allocator minimum rather than reserving tens of MiB. Refs COD-3222
Add a fixture with two non-inlinable malloc call paths and privileged tests over it: distinct call paths get distinct identities with module mappings for the binary and libc, repeated calls deduplicate, and the default-off path still reports allocations. Two cases guard failure modes the default budget cannot reach. The maximum copy budget is the only configuration that exercises the verifier's instruction limit, since the frozen rodata makes the copy and hash loops scale with the configured size. Shrinking the frame-pointer map to one slot proves exhaustion costs only the fallback chain, never an allocation event. Refs COD-3222
Merging this PR will degrade performance by 36.4%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ❌ | WallTime | encode_events_realistic[16] |
122.2 ms | 212.1 ms | -42.41% |
| ❌ | WallTime | encode_events_realistic[8] |
143.9 ms | 231.4 ms | -37.8% |
| ❌ | WallTime | encode_events_realistic[4] |
216.4 ms | 301.3 ms | -28.18% |
Tip
Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.
Comparing cod-3222-add-ebpf-based-dwarffp-unwinding (83de75e) with main (e89df29)
not-matthias
force-pushed
the
cod-3222-add-ebpf-based-dwarffp-unwinding
branch
from
August 28, 2026 15:10
573a77e to
83de75e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds raw allocation-stack capture to memtrack and ships everything needed for off-box unwinding.
At every allocator entry the eBPF program copies the caller's user stack (chunked, budget-capped, FNV-1a-hashed) and walks frame pointers in-kernel. Definitions are deduplicated by hash in-kernel: one
StackDefinitionevent (raw bytes, registers, FP chain) per distinct stack, referenced by astack_hashon allocation events. Everything flows through the ordinaryMemtrackArtifactevent stream; unwinding and symbolication happen server-side later.After a capture-enabled run, the runner decodes the artifact and reuses the perf walltime machinery to dump per-module symbols, unwind data, and debug info into the profile folder, plus a
memory_metadata.jsonwith per-pid process names.Refs COD-3222