Skip to content

Reuse a scratch buffer in light_write_packet to avoid per-packet allocation#2178

Open
MerinoSheep wants to merge 7 commits into
seladb:devfrom
MerinoSheep:perf/pcapng-write-scratch-buffer-v2
Open

Reuse a scratch buffer in light_write_packet to avoid per-packet allocation#2178
MerinoSheep wants to merge 7 commits into
seladb:devfrom
MerinoSheep:perf/pcapng-write-scratch-buffer-v2

Conversation

@MerinoSheep

Copy link
Copy Markdown
Contributor

Summary

  • Reuse a scratch buffer kept on the light_pcapng_t handle when building enhanced
    packet blocks in light_write_packet, instead of calloc/free-ing one for every
    written packet. The buffer grows on demand and is released in light_pcapng_close.
  • Only the PADD32 padding tail is zeroed on reuse, since the fixed EPB header fields
    and the packet payload are fully overwritten on each write.
  • Add TestPcapNgFileWriteScratchReuse, which writes packets of varying sizes (mixing
    buffer-grow and buffer-reuse transitions), then reads them back and verifies data and
    per-packet comments round-trip exactly.

Performance

Measured writing 2,000,000 packets to a tmpfs file, 5 runs each, comparing this branch
against its base with only the patched file reverted:

Packet size Before (median) After (median) Δ
64 B 4,584,602 pkts/s 4,990,264 pkts/s +8.8%
128 B 3,142,929 pkts/s 3,449,104 pkts/s +9.7%
256 B 2,236,526 pkts/s 2,489,930 pkts/s +11.3%
512 B 1,489,529 pkts/s 1,519,552 pkts/s +2.0%
1500 B 439,037 pkts/s 453,986 pkts/s +3.4%
9000 B 128,028 pkts/s 127,790 pkts/s ~0%

Gains are largest for small-to-medium packets, where the per-packet allocation
overhead removed by this change is a larger fraction of total write cost.

Test plan

  • Bin/Pcap++Test -n — all pcapng tests pass, including the new one
  • MemPlumber leak checks pass (run by default per test)
  • New test covers small/large buffer grow and reuse transitions, with and without
    per-packet comments
  • Full project (library, examples, tests) builds cleanly against latest dev
  • clang-format and cppcheck checked manually against the pre-commit hook
    invocations (no diffs / no warnings)

Made with Cursor

merino and others added 4 commits June 27, 2026 06:35
…cation.

Keep a reusable buffer on the light_pcapng_t handle for building enhanced
packet blocks instead of calloc/free-ing one for every written packet. The
buffer grows on demand and is released in light_pcapng_close. Only the PADD32
padding tail is zeroed since the fixed EPB fields and packet data are fully
overwritten on each write.

Co-authored-by: Cursor <cursoragent@cursor.com>
Write packets of varying sizes through a single writer, mixing small-then-large
and large-then-small transitions, then read them back and verify data and
comments round-trip exactly. Covers the reusable write buffer added to
light_write_packet.

Co-authored-by: Cursor <cursoragent@cursor.com>
Move each PCPP patch marker onto its own line, separate from the explanatory
text, and rewrite the comments to focus on why the scratch buffer exists and
why only its padding tail needs zeroing, rather than restating what the code
does.

Co-authored-by: Cursor <cursoragent@cursor.com>
@MerinoSheep MerinoSheep requested a review from seladb as a code owner July 1, 2026 23:29
@MerinoSheep

Copy link
Copy Markdown
Contributor Author

hmmm, let me fix tests failures

merino and others added 3 commits July 2, 2026 00:50
The payload layer was held in a unique_ptr declared after (and thus
destroyed before) the owning packet, so the packet's destructor later
walked its layer chain into freed memory. This only crashed reliably
under stricter allocators (MSVC debug heap on Windows CI, ASan), which
is why it slipped through locally. Let the packet own the layer instead
via addLayer's ownInPacket flag so their lifetimes are tied together.

Found by building with -fsanitize=address,undefined, which reproduced
the same use-after-free that the Windows CI jobs were hitting.

Co-authored-by: Cursor <cursoragent@cursor.com>
"No longer freed here" only makes sense to someone comparing against
the pre-patch code. State the ownership invariant on its own terms
instead, since that's what a reader without that history needs at
this call site.

Co-authored-by: Cursor <cursoragent@cursor.com>
Use a PcapFileNamesDef.h path macro like every other read/write test in
this file instead of a locally-scoped literal, and drop the std::remove
cleanup, which no other test here does (output files are gitignored,
and the cleanup was skipped anyway on any assertion failure since
PTF_ASSERT_* returns early). Also drops <cstdio> and <memory>, which
were only needed by code that no longer exists in this test.

Co-authored-by: Cursor <cursoragent@cursor.com>
@codecov

codecov Bot commented Jul 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.18182% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 82.80%. Comparing base (c0c6ec5) to head (7697002).

Files with missing lines Patch % Lines
Tests/Pcap++Test/Tests/FileTests.cpp 97.61% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #2178      +/-   ##
==========================================
+ Coverage   82.78%   82.80%   +0.01%     
==========================================
  Files         331      331              
  Lines       60050    60097      +47     
  Branches    12427    12416      -11     
==========================================
+ Hits        49713    49762      +49     
  Misses       9454     9454              
+ Partials      883      881       -2     
Flag Coverage Δ
23.11.6 7.29% <0.00%> (+0.02%) ⬆️
24.11.5 7.24% <0.00%> (-0.03%) ⬇️
25.11.1 7.29% <0.00%> (-0.01%) ⬇️
alpine320 76.88% <96.96%> (+0.01%) ⬆️
fedora42 76.44% <96.96%> (+0.02%) ⬆️
macos-14 82.28% <96.36%> (+0.01%) ⬆️
macos-15 82.27% <96.36%> (+0.01%) ⬆️
mingw32 70.95% <ø> (ø)
mingw64 70.93% <ø> (+0.09%) ⬆️
npcap ?
rhel94 76.25% <96.96%> (+0.02%) ⬆️
ubuntu2204 76.29% <96.96%> (+0.01%) ⬆️
ubuntu2204-icpx 59.29% <ø> (-0.03%) ⬇️
ubuntu2404 76.60% <94.11%> (+0.05%) ⬆️
ubuntu2404-arm64 76.57% <96.96%> (+0.01%) ⬆️
ubuntu2604 76.52% <96.96%> (-0.01%) ⬇️
unittest 82.80% <98.18%> (+0.01%) ⬆️
windows-2022 85.80% <ø> (+0.12%) ⬆️
windows-2025 85.54% <ø> (+0.12%) ⬆️
winpcap 85.84% <ø> (+0.20%) ⬆️
xdp 52.81% <0.00%> (-0.08%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant