perf: gather Linear-mode window input more efficiently - #24034
Open
neilconway wants to merge 1 commit into
Open
Conversation
LinearSearch::evaluate_partition_batches issued one take_record_batch call per partition present in the input batch. For batches with many partitions, this is inefficient. Instead, we can build a Vec of the batch's row indices that groups the rows by partition, gather all rows with a single `take_record_batch` call, and hand each partition a slice of the result. Batches that contain a single partition skip the gather entirely. Sliced partition batches already flow through this path: the Sorted searcher returns record_batch.slice(..), and downstream code (PartitionBatchState::extend, the new-partition store in update_partition_batch, prune_partition_batches) handles non-zero offsets. Memory caveat: the emitted slices share the gathered batch's buffers. A partition that never receives rows again retains its slice and therefore pins the gathered batch's buffers (up to one input batch worth of memory per input batch in the worst case). This could be addressed, e.g., with a compaction pass to copy long-lived slices into owned buffers, but I have omitted that for now. Benchmarks: - linear 100 partitions: 44.3 ms -> 44.1 ms (within noise) - linear 10000 partitions: 199.8 ms -> 170.1 ms (-14.9%) - linear sparse 32768 partitions: 224.6 ms -> 205.3 ms (-8.6%) - linear rows 10000 partitions: 169.0 ms -> 142.0 ms (-15.9%) - linear multi 10000 partitions: 295.9 ms -> 268.2 ms (-9.4%) - sorted 10000 partitions: 34.0 ms -> 34.5 ms (+1.3%; the Sorted path is untouched -- binary layout / session noise)
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #24034 +/- ##
=======================================
Coverage 80.85% 80.85%
=======================================
Files 1101 1101
Lines 374933 375018 +85
Branches 374933 375018 +85
=======================================
+ Hits 303166 303237 +71
- Misses 53671 53679 +8
- Partials 18096 18102 +6 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Contributor
|
FYI @avantgardnerio / @2010YOUY01 who were perhaps interested in window function performance |
Dandandan
reviewed
Aug 3, 2026
| // Handle hash collusions with an equality check: | ||
| row.eq(&result[*group_idx].0) | ||
| // Handle hash collisions with an equality check: | ||
| row.eq(&keys[*group_idx]) |
Dandandan
approved these changes
Aug 3, 2026
Dandandan
left a comment
Contributor
There was a problem hiding this comment.
Nice result for a (relatively) small change!
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.
Which issue does this PR close?
BoundedWindowAggExecinLinearmode is slow for many-partitions #23982Rationale for this change
LinearSearch::evaluate_partition_batchesissued onetake_record_batchcall per partition present in the input batch. For batches with many partitions, this is inefficient.Instead, we can build a Vec of the batch's row indices that groups the rows by partition, gather all rows with a single
take_record_batchcall, and hand each partition a slice of the result. Batches that contain a single partition skip the gather entirely.Memory caveat: the emitted slices share the gathered batch's buffers. A partition that never receives rows again retains its slice and therefore pins the gathered batch's buffers (up to one input batch worth of memory per input batch in the worst case). This could be addressed, e.g., with a compaction pass to copy long-lived slices into owned buffers, but I have omitted that for now.
Benchmarks: (using #24032)
What changes are included in this PR?
get_per_partition_indicesand rename tocompute_partition_permutationAre these changes tested?
Yes, new test added.
Are there any user-facing changes?
No.