You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
perf(filtered-read): consolidate take-shaped masked reads off the consumer (#7783)
## Problem
A masked (row-set) read whose plan touches many fragments with only a
few rows each — the shape a take-style workload produces — emits one
tiny batch per fragment (a batch never spans fragments). The per-batch
pipeline driving executes inline in whichever task polls the node's
output, so concurrent small reads serialize on their consumers. A
flamegraph of 64 concurrent take-100 masked reads shows the polling
thread saturated by the `task_stream` unfold/buffer machinery while
workers sit idle.
## Fix
For take-shaped plans only — a row-set input, at least 8 fragments
planned non-empty, and fewer than 1024 planned rows per fragment on
average — pump the read on a spawned task and hand the consumer
consolidated batches (merge-only: order preserved, any batch already at
the target passes through whole).
Everything else is byte-for-byte unchanged: plain scans, single-fragment
reads, dense masked reads (including filtered scans, whose planned rows
are a pre-refine upper bound) and the byte-based rechunk path keep their
batch boundaries, first-batch latency and backpressure.
## Benchmarks
Single node, 100M rows / 100 fragments (NVMe, warm), fixed-seed
scattered row sets, identical physical I/O between arms:
| cell | before | after |
|---|---|---|
| masked take-100, concurrency 64 | 291 QPS | **634 QPS** (TakeExec:
485) |
| masked take-100K, concurrency 32 | 5.4 QPS | **12.1 QPS** |
| masked take-100 / take-10K / take-100K, concurrency 1 | 339 / 12.9 /
11.4 | 341 / 13.9 / 10.3 (within noise) |
| scan 2M rows, concurrency 1 / 8 | 287 / 175 | 256 / 158 (untouched
code path, run-to-run variance) |
## Testing
- New `test_take_shaped_mask_consolidation` covers the consolidated
shape (single output batch, fragment order preserved), the few-fragment
counterexample and the dense counterexample (per-fragment boundaries
kept). It also pins the gate to count only fragments planned non-empty.
- Existing `filtered_read` and `scanner` suites pass (the intermittent
suite-mode failures reproduce on main without this change).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Performance Improvements**
* Improved masked read execution by consolidating many small
per-fragment results into fewer larger batches when appropriate.
* Reduced batch count for “take-shaped” masked reads to speed up
downstream processing.
* Preserved existing behavior for dense masked reads and for
configurations that rely on byte-based rechunking or do not meet
consolidation conditions.
* **Tests**
* Added a new test to validate batch consolidation for take-shaped
masked reads and to confirm batch boundaries are maintained for
dense/too-few-fragment scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
0 commit comments