Skip to content

fix: bound WindowAgg and grouped TopK output batches - #26788

Open
koriyoshi2041 wants to merge 3 commits into
apache:mainfrom
koriyoshi2041:fix-bounded-blocking-output
Open

koriyoshi2041 wants to merge 3 commits into
apache:mainfrom
koriyoshi2041:fix-bounded-blocking-output

Conversation

@koriyoshi2041

Copy link
Copy Markdown
Contributor

Closes #26772.

Problem

WindowAggExec and grouped TopK materialize their final result and currently emit it as one RecordBatch. Large results therefore bypass datafusion.execution.batch_size and make one stream poll hand an oversized batch to downstream operators.

Fix

Carry the configured batch size into both streams, retain the materialized result, and emit zero-copy RecordBatch::slice chunks across successive polls. Output metrics are recorded per emitted chunk, and WindowAggExec releases its buffered input batches after computing the result.

Tests

  • cargo test -p datafusion-physical-plan grouped_topk_stream::tests --lib
  • cargo test -p datafusion-physical-plan window_agg_exec::tests --lib
  • cargo clippy -p datafusion-physical-plan --lib --tests -- -D warnings
  • cargo fmt --all -- --check
  • git diff --check

The regressions assert 4/4/2 and 2/2/1 output shapes, unchanged values, and per-chunk row/batch metrics.

Risk

Low. Result computation, ordering, and values are unchanged. Slicing is zero-copy; the behavioral change is limited to output batch boundaries and the matching output-batch metric count.

@github-actions github-actions Bot added the physical-plan Changes to the physical-plan crate label Oct 27, 2026
@koriyoshi2041

Copy link
Copy Markdown
Contributor Author

Revalidated this against current main (636590bf4). The branch merges cleanly despite the intervening changes, and the focused suites pass on the merged tree:

  • grouped_topk_stream::tests: 2/2
  • window_agg_exec::tests: 13/13

The 4/4/2 and 2/2/1 output-bound regressions still exercise the current code paths, so I did not add a churn-only commit.

@kosiew kosiew 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.

Have you considered async_try_stream + into_stream() pattern used by the other aggregate streams (e.g. single_stream.rs), which would remove the output-cursor fields and completion guards added here.

@koriyoshi2041

Copy link
Copy Markdown
Contributor Author

Yes. I traced the single_stream.rs pattern, and it fits both blocking operators better than the explicit Poll state added here.

For WindowAggStream, the generator can consume input.next().await, drop the input, compute the materialized result once, and emit result.slice(offset, batch_size) from a local loop. For grouped TopK, it can consume and intern inputs in the same way, then emit the final materialized batch. That removes done, output, and output_offset from the structs while preserving the 4/4/2 and 2/2/1 regression expectations. Wrapping each generator in RecordBatchStreamAdapter/ObservedStream also keeps output metrics at the emitted-slice boundary.

I will revise the branch in that form and rerun the two focused suites.

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

Labels

physical-plan Changes to the physical-plan crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WindowAggExec and grouped TopK can exceed batch_size

2 participants