perf(memtrack): reduce serialization bottleneck#436
Conversation
Merging this PR will improve performance by 44.86%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ⚡ | Simulation | write_events[1000000] |
2.1 s | 1.4 s | +47.8% |
| ⚡ | Simulation | write_events[100000] |
207.3 ms | 141.3 ms | +46.74% |
| ⚡ | Simulation | write_events[10000] |
20 ms | 13.9 ms | +43.69% |
| ⚡ | Simulation | write_events[500000] |
1,036.6 ms | 733.6 ms | +41.31% |
| 🆕 | WallTime | encode_events_realistic[16] |
N/A | 121.9 ms | N/A |
| 🆕 | WallTime | encode_events_realistic[4] |
N/A | 216.1 ms | N/A |
| 🆕 | WallTime | encode_events_realistic[8] |
N/A | 144.5 ms | N/A |
| 🆕 | WallTime | write_events[10000] |
N/A | 7 ms | N/A |
| 🆕 | WallTime | write_events[100000] |
N/A | 72 ms | N/A |
| 🆕 | WallTime | write_events[1000000] |
N/A | 771.5 ms | N/A |
| 🆕 | WallTime | write_events[500000] |
N/A | 387.4 ms | N/A |
| 🆕 | Simulation | encode_events_realistic[16] |
N/A | 1.2 s | N/A |
| 🆕 | Simulation | encode_events_realistic[8] |
N/A | 1.2 s | N/A |
| 🆕 | Simulation | encode_events_realistic[4] |
N/A | 1.2 s | N/A |
Tip
Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.
Comparing cod-3071-fix-serialization-bottleneck (d06d42e) with main (705245d)
381bac8 to
9be9b22
Compare
Greptile SummaryThis PR replaces the single-threaded, single-zstd-frame memtrack encoding pipeline with a parallel one: events are batched into 64 K-event windows, each window is compressed as independent zstd frames across a Rayon worker pool, and frames are written in order so the output is fully deterministic. It also migrates the eBPF ring-buffer channel from
Confidence Score: 5/5Safe to merge. The core encoding logic is correct, multi-frame decoding works with zstd 0.13.3's default multiple-members behavior, and ordering is verified by the new tests. The parallel pipeline, ownership changes, and channel migration are all well-reasoned and covered by tests. The two findings are style and benchmark-accuracy nits that don't affect production correctness. No files require special attention. The benchmark in Important Files Changed
|
a225638 to
9561cdd
Compare
9561cdd to
9292b3f
Compare
346a162 to
99b9b68
Compare
…t zstd compression bottleneck
Callers that encode a frame into an in-memory buffer need the buffer back after the zstd stream is finalized, so frames can be composed into a larger artifact stream. Refs COD-3071
Group events into fixed-size frames and compress them across a rayon pool, writing windows in input order. Bounds peak memory regardless of run length and removes the single-threaded compression bottleneck. Refs COD-3071
…race Generate a seeded malloc/free/realloc/mmap workload with a live-heap model instead of uniform random events, and sweep worker counts. Refs COD-3071
Forward ring buffer events over a crossbeam channel directly instead of through an extra keep-alive forwarding thread. On shutdown, consume the ring buffer once more so events emitted after the last poll are not lost, then close the channel. Refs COD-3071
Feed the poller's event channel straight into encode_events on one thread, sized to available parallelism. Shutdown is now deterministic: stop the poller, which drains stragglers and closes the channel, then join the pipeline. Fixes COD-3071
itertools::chunks erases the iterator size hint, so collecting each window grew by doubling (~29% of encode driver time in reallocation). A single pre-sized buffer reused across windows removes the growth and the chunk-adapter bookkeeping: encode_events_realistic median drops 21%/17%/9% at 16/8/4 workers.
99b9b68 to
78d5ae2
Compare
Summary
MemtrackEventserialization with a byte-identical manual serializerMemtrackWriter::finishreturn encoded frame bytes for batchingVerification
cargo test -p runner-shared artifacts::memtrackcargo test -p runner-sharedcargo check -p runner-sharedcargo test --manifest-path crates/memtrack/Cargo.tomlvia Nix shell with libclang/build deps; eBPF integration cases compiled but were ignored becauseGITHUB_ACTIONSwas unsetcargo bench -p runner-shared --bench memtrack_writerNotes
memtrack_writerbench measures the Phase A single-writer encoder path only, not the full parallel memtrack pipeline.