Skip to content

[QDP] StreamingProducer: use VecDeque for O(1) buffer advance - #1462

Open
0lai0 wants to merge 2 commits into
apache:mainfrom
0lai0:refatcor-trackE3
Open

[QDP] StreamingProducer: use VecDeque for O(1) buffer advance#1462
0lai0 wants to merge 2 commits into
apache:mainfrom
0lai0:refatcor-trackE3

Conversation

@0lai0

@0lai0 0lai0 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Related Issues

Closes #1436

Changes

  • Bug fix
  • New feature
  • Refactoring
  • Documentation
  • Test
  • CI/CD pipeline
  • Other

Why

StreamingProducer tracked consumed elements with a buffer_cursor and, once the cursor passed the halfway mark (BUFFER_COMPACT_DENOM), reclaimed the prefix with Vec::drain(..cursor) — an O(n) memmove of the retained tail, on the streaming hot path.

A VecDeque advances its head instead, so discarding a consumed prefix never shifts the data that is still live: O(1) amortized buffer advance, no periodic compaction pass, and no change in output.

How

  • buffer: Vec<T> + buffer_cursor: usizebuffer: VecDeque<T>; removed the now-unused BUFFER_COMPACT_DENOM compaction heuristic
  • produce() copies the batch out of as_slices() (stitching both halves when a batch straddles the ring's wrap boundary), then drain(..take)s the consumed prefix. Copying via the slices keeps the batch copy on extend_from_slice's bulk path — Drain is not TrustedLen, so extend(drain) would copy element by element. Recycled batch buffers are still reused, so the batch copy itself stays allocation-free
  • Refills use extend(&scratch[..written]) rather than .iter().copied(): VecDeque specializes Extend<&T> for T: Copy into a bulk copy_slice
  • The build path pre-reserves the steady state (batch_size * sample_size + initial_cap, the peak live length) so the ring never reallocates mid-run. VecDeque::from(Vec) reuses the existing allocation, so this only tops the capacity up.

Checklist

  • Added or updated unit tests for all changes
  • Added or updated documentation for all changes

@0lai0
0lai0 requested a review from 400Ping as a code owner August 5, 2026 06:14

@viiccwen viiccwen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thx for the correctness and capacity tests. Since the main change is hot-path performance, could you also provide a small reproducible before/after benchmark?

It would be helpful to compare the current Vec + cursor implementation against this VecDeque implementation.

@rich7420

rich7420 commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

LGTM.

@0lai0

0lai0 commented Aug 9, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @viiccwen and @rich7420
Added beanch mark make -C qdp bench_streaming_buffer
(before = frozen pre-change producer; after = shipped StreamingProducer)

Buffer-only (refill chunk 65536), Xeon w3-2435, --release:

batch:chunk before after speedup
1:16 782 ns 504 ns 1.55x
1:4 3370 ns 2480 ns 1.36x
1:1 9668 ns 9716 ns 1.00x
4:1 54176 ns 54469 ns 0.99x

E2E via Parquet: ~1.01–1.02x (decode dominates). Win only when batch ≪ chunk; at 1:1+ both do the same work.
Happy to reword the PR around #1436's O(1) advance / constant-capacity criteria rather than throughput

@viiccwen viiccwen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left comments.

Comment thread qdp/Makefile

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need to expose any benchmark experiment in command.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need this.

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.

[Refactor] StreamingProducer: use VecDeque for O(1) buffer advance

3 participants