perf(scan): intra-file decode parallelism — sub-split large chunk spans#62
Merged
Conversation
SplitBy::Layout now sub-divides any span between adjacent chunk boundaries wider than IDEAL_SPLIT_SIZE (100k rows) into evenly sized row-range splits, so files with few large chunks decode across multiple cores. Subdivision only inserts points strictly between existing adjacent boundaries: the half-open ranges consumers derive remain a contiguous, non-overlapping, exact partition of the same rows. The arithmetic saturates at u64::MAX. Tests: unit/property/overflow coverage for the subdivision helper, an end-to-end test that a 250k-row single flat chunk scans correctly across sub-divided splits with bounded split sizes, an rstest-parameterized end-to-end test for fixed-size SplitBy::RowCount scans (previously only covered at the boundary-math level), and an end-to-end test that ~120-byte string columns written with the default strategy keep their natural ~8k-row chunk splits untouched by the cap. Signed-off-by: Luke Kim <80174+lukekim@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Improves scan-time parallelism by enhancing SplitBy::Layout to further subdivide large inter-chunk row spans into smaller row-range splits (capped at ~100k rows), enabling multi-core decode even for files with very few large chunks.
Changes:
- Added
subdivide_large_spansto insert additional split boundaries inside large adjacent chunk spans forSplitBy::Layout. - Updated
SplitBy::Layoutdocumentation and behavior to apply the sub-splitting cap. - Added E2E tests in
vortex-filevalidating subdivision on a single large flat chunk, regression coverage forSplitBy::RowCount, and ensuring fine-grained string chunking remains small; introducedrstestas a dev dependency.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| vortex-layout/src/scan/split_by.rs | Implements span subdivision for SplitBy::Layout and adds unit/property/overflow tests. |
| vortex-file/src/tests.rs | Adds end-to-end coverage for split subdivision behavior and SplitBy::RowCount scan correctness. |
| vortex-file/Cargo.toml | Adds rstest as a dev-dependency for parameterized tests. |
| Cargo.lock | Updates lockfile for the added dev-dependency. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Introduce a test-local MAX_SPLIT_ROWS mirroring the private IDEAL_SPLIT_SIZE instead of repeating 100_000, and bound the string-chunk test relative to the cap (< MAX_SPLIT_ROWS / 4) rather than pinning the current ~8k repartition default. Signed-off-by: Luke Kim <80174+lukekim@users.noreply.github.com>
krinart
approved these changes
Jun 12, 2026
This was referenced Jun 12, 2026
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.
What
SplitBy::Layoutnow sub-divides any span between adjacent chunk boundaries wider thanIDEAL_SPLIT_SIZE(100k rows) into evenly sized row-range splits, so a file with few large chunks (e.g. a single flat layout, or byte-targeted int columns that coalesce to ~262k rows/chunk) decodes across multiple cores instead of one.Correctness
Subdivision only inserts points strictly between existing adjacent boundaries — it never moves or removes one — so the half-open ranges consumers derive (
tuple_windows) remain a contiguous, non-overlapping, exact partition of the same rows. Spans at or below the cap pass through untouched (fast-path no-op). All three boundary consumers (RepeatedScan,VortexFile::splits(), the DataFusion repartitioner) operate on arbitrary ranges; sub-chunk ranges were already exercised bySplitBy::RowCount. The arithmetic saturates atu64::MAX.Observable behavior
For files whose merged (projected-column) chunk boundaries leave spans > 100k rows,
VortexFile::splits()(incl. Python bindings) returns more, smaller ranges; scans emit smaller batches; DataFusion gets real repartitioning where a single-chunk file previously collapsed to one partition. Fine-grained files (e.g. ~8k-row string chunks from the default 1 MiB block target) are untouched.Testing
subdivide_large_spans(no-op, large single chunk, mixed gaps, exact-coverage property,u64::MAXboundary).SplitBy::RowCountscans (unaligned 33,333 and exceeds-file 300,000 cases) — previously only covered at the boundary-math level.cargo nextest run -p vortex-layout -p vortex-file— 170 passed.cargo clippy --all-targets— no diagnostics in changed files.Split out of #60 (second of two independent changes; companion: #61).