perf: skip eval of standard window functions for unchanged partitions - #24532
perf: skip eval of standard window functions for unchanged partitions#24532neilconway wants to merge 1 commit into
Conversation
In Linear mode, BoundedWindowAggStream's evaluation sweep visits every live partition for every window expression on every input batch. For standard (non-aggregate) window functions (e.g., row_number, rank, lag/lead, and nth_value), a partition that received no rows since the previous evaluation pass can be skipped: evaluating a function only depends on the contents of the partition itself. New rows are detected with a received-row counter on PartitionBatchState that each expression's WindowAggState snapshots at the end of every evaluation pass. This test is deliberately different from the "every buffered row has a result" test used to skip aggregate window expressions (apache#24127). Aggregate evaluation also consults the ORDER BY values of the most recent input row across all partitions, which can produce new results for a partition whose own input is unchanged. Benchmarks: - linear dense count 100: 44.4 ms -> 44.0 ms (-0.8%) - linear dense count 10000: 161.9 ms -> 160.7 ms (-0.9%) - linear sparse count 32768: 89.3 ms -> 88.4 ms (-0.9%) - linear dense count rows-frame: 136.4 ms -> 136.1 ms (~noise) - linear dense count+sum 10000: 253.1 ms -> 235.3 ms (-7.0%) - linear dense row_number 10000: 114.7 ms -> 110.9 ms (-3.2%) - linear sparse row_number 32768: 73.5 ms -> 42.2 ms (-42.5%) - linear sparse lead 32768: 108.5 ms -> 46.6 ms (-57.0%) - linear dense rank 10000: 125.8 ms -> 121.5 ms (-3.4%) - sorted count 10000: 34.5 ms -> 33.4 ms (-3.6%)
|
Thank you for opening this pull request! Reviewer note: cargo-semver-checks reported the current version number is not SemVer-compatible with the changes in this pull request (compared against the base branch). Details |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #24532 +/- ##
========================================
Coverage 81.31% 81.31%
========================================
Files 1117 1117
Lines 395911 396290 +379
Branches 395911 396290 +379
========================================
+ Hits 321918 322249 +331
- Misses 55177 55197 +20
- Partials 18816 18844 +28 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
| @@ -299,6 +331,7 @@ impl PartitionBatchState { | |||
| pub fn extend(&mut self, batch: &RecordBatch) -> Result<()> { | |||
| self.record_batch = | |||
There was a problem hiding this comment.
Not this PR per se, but something I notice right now.
How often is this extend called? It would probably be better to buffer to a Vec (and delay concatenation) or use the batch coalescer (https://docs.rs/arrow/latest/arrow/compute/struct.BatchCoalescer.html) here otherwise it would be O(n^2) and do a lot of copying.
Which issue does this PR close?
BoundedWindowAggExecinLinearmode is slow for many-partitions #23982Rationale for this change
In Linear mode,
BoundedWindowAggStreamdoes an evaluation sweep that visits every live partition for every window expression on every input batch. For standard (non-aggregate) window functions (e.g., row_number, rank, lag/lead, and nth_value), a partition that received no rows since the previous evaluation pass can be skipped: evaluating a function only depends on the contents of the partition itself.New rows are detected with a received-row counter on
PartitionBatchStatethat each expression'sWindowAggStatesnapshots at the end of every evaluation pass.This test is deliberately different from the "every buffered row has a result" test used to skip aggregate window expressions (#24127). Aggregate evaluation also consults the ORDER BY values of the most recent input row across all partitions, which can produce new results for a partition whose own input is unchanged.
Benchmarks:
What changes are included in this PR?
Are these changes tested?
Yes; new tests added.
Are there any user-facing changes?
No.