Skip to content

perf: avoid cloning ByteView buffer lists in take and filter - #10708

Open
YimingQiao wants to merge 1 commit into
apache:mainfrom
YimingQiao:perf/share-byte-view-buffer-list
Open

perf: avoid cloning ByteView buffer lists in take and filter#10708
YimingQiao wants to merge 1 commit into
apache:mainfrom
YimingQiao:perf/share-byte-view-buffer-list

Conversation

@YimingQiao

@YimingQiao YimingQiao commented Aug 16, 2026

Copy link
Copy Markdown

Which issue does this PR close?

Rationale for this change

This change follows directly from the existing ByteView design history:

The downstream impact is concrete. apache/datafusion#16206 describes hash joins where concatenating build-side batches produces ByteView payload columns with many backing buffers, and constructing join output repeatedly calls take. In that pattern, cloning and later dropping every buffer handle can become a significant part of execution time. Arrow issue #10692 provides a compact multi-stage take and BatchCoalescer reproduction of the same ownership-metadata amplification.

take_byte_view and filter_byte_view do not yet use this shared representation. They rebuild the collection with data_buffers().to_vec(), allocating a new collection and cloning every Buffer. This makes the ownership bookkeeping for selection O(number of backing buffers), despite retaining exactly the same complete buffer list.

Selection already copies the chosen views while leaving their payloads zero-copy. The cost of retaining the unchanged backing-buffer collection should therefore not grow with the number of entries in that collection. This PR completes that narrow part of the earlier design while leaving buffer canonicalization as a separate problem.

What changes are included in this PR?

  • Add GenericByteViewArray::data_buffers_shared() -> Arc<[Buffer]> to obtain shared ownership of the backing-buffer collection in O(1).
  • Use this API in the ByteView take and filter kernels instead of rebuilding the collection.
  • Verify for both StringView and BinaryView that selection results share the input buffer collection.
  • Add a take benchmark that varies the number of backing-buffer entries.

data_buffers() remains the borrowed inspection API returning &[Buffer]. The new method returns shared ownership directly, rather than exposing &Arc<[Buffer]> and requiring callers to know that they must call Arc::clone. Returning Arc<[Buffer]> is consistent with the existing into_parts() return type and the types accepted by the ByteView array constructors.

This PR only removes repeated ownership-metadata cloning. It retains the same complete collection of backing buffers as before. It does not prune or deduplicate buffer entries, remap views, run GC, or copy string/binary payloads. The broader buffer-fragmentation problem described in #10692 remains separate.

Are these changes tested?

cargo fmt --all -- --check
cargo test -p arrow-array -p arrow-select
cargo clippy -p arrow-array -p arrow-select --all-targets --all-features -- -D warnings
cargo doc -p arrow-array --no-deps

The new Criterion benchmark takes 8,192 views distributed across a varying number of buffer entries. The entries share one immutable payload allocation, isolating collection-ownership cost from payload size. main and this PR were built in separate Cargo target directories on an Intel Xeon Platinum 8474C:

Buffer entries main This PR Speedup
1 5.4900 us 5.4619 us 1.01x
16 5.7342 us 5.4577 us 1.05x
256 9.2806 us 5.4518 us 1.70x
4,096 65.774 us 5.4584 us 12.05x

Existing normal-size benchmarks did not regress:

Benchmark main This PR
take stringview 512 504.73 ns 439.40 ns
take stringview 1024 872.36 ns 773.48 ns
filter context mixed string view (kept 1/2) 73.406 us 72.083 us

Are there any user-facing changes?

There is one additive public method, GenericByteViewArray::data_buffers_shared. ByteView selection results now share the immutable backing-buffer collection instead of allocating an equivalent collection. Logical values, null handling, buffer indexes, payload lifetimes, and GC behavior are unchanged.

AI assistance

I used OpenAI Codex to help inspect the relevant implementation history, draft the patch and tests, and prepare the benchmark harness and PR text. I reviewed the implementation and benchmark methodology and ran the checks above locally.

@github-actions github-actions Bot added arrow Changes to the arrow crate arrow-select arrow-array labels Aug 16, 2026
@YimingQiao
YimingQiao marked this pull request as draft August 16, 2026 16:00
@YimingQiao
YimingQiao force-pushed the perf/share-byte-view-buffer-list branch from c884697 to 46c989e Compare August 16, 2026 16:01
@YimingQiao YimingQiao changed the title perf: share ByteView buffer lists in take and filter perf: avoid cloning ByteView buffer lists in take and filter Aug 16, 2026
@YimingQiao
YimingQiao marked this pull request as ready for review August 16, 2026 16:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arrow Changes to the arrow crate arrow-array arrow-select

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant