Repository navigation
perf(scan): merge narrow splits at boundaries only some fields of a struct have - #67
Conversation
gitRasheed
left a comment
There was a problem hiding this comment.
The merge logic looks right. A port of merge_small_spans held up under a few hundred thousand random and exhaustive cases: it always keeps the ends and the hard boundaries and never adds one. Two things before merge:
-
The tests the description lists aren't in the commit: no
merge_small_spansunit or property tests, and no scan_builder changes. The two new struct tests stop atregister_splits, and the existingSplitBytests use a stub that never marks anything soft, so nothing covers soft-boundary merging. Could you add the merge tests and oneLayoutSubSplittingtest overmisaligned_struct_layoutthat checks the resulting boundaries? -
The shared-boundary check (struct_/reader.rs:547) binary-searches every field for each boundary of each field, so it's F² x B x log B per struct. Aligned wide structs pay the most: 1,000 fields with 50 chunks each is 50M searches, and
SplitBy::Layoutpays it too, then drops the soft marks. Counting how many fields have each row (concatenate, sort, soft when the count is under F) does it in one pass.
…truct have A scan splits wherever any column's chunk ends, and a split decodes the whole chunk of every column it overlaps. Where a struct's fields chunk at unrelated rows, as list elements and dictionary-encoded columns of a wide nested file do, the union holds spans of a few dozen rows, and successive splits each decode the same chunks of the other fields. The struct reader now marks the boundaries only some of its fields have as soft. SplitBy::LayoutSubSplitting merges spans ending at soft boundaries up to DEFAULT_MIN_SPLIT_ROWS (8,192, or max_rows if smaller). Boundaries every field has, and those layouts above the struct register, such as top-level chunk ends, are never merged, so files whose columns chunk alike split as before. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Christopher Wirt <[email protected]>
Compute the shared boundary intersection once, preserve validity boundaries, and move inherited soft marks without cloning their buffer. Add merge invariants, real-layout regression coverage, and a wider split-collection benchmark case. Signed-off-by: Christopher Wirt <[email protected]>
30be3a4 to
aab5de1
Compare
|
Thanks @gitRasheed, agreed on both. Pushed aab5de1 with the fixes:
The review also caught a validity boundary becoming soft when it overlapped a data-field boundary. That's fixed, with a regression that failed before the change. Inherited child soft marks are preserved. Checks passed: 836 layout tests, all-target/all-feature Clippy for layout and file with The first Java run ran out of disk space. I freed the temporary build artifacts and ran the suites sequentially; no test assertions were changed. Linux musl CI has now passed the Rust workspace tests too. |
gitRasheed
left a comment
There was a problem hiding this comment.
Thanks. The intersection is computed once now, and the real-layout LayoutSubSplitting tests cover the merge path. Good catch on validity boundaries going soft.
Fixes #61.
Problem
Change
RowSplits, and the struct takes their union, marking any boundary not every field has as soft. A single-field struct registers exactly as before.SplitBy::LayoutSubSplittingmerges spans ending at a soft boundary until they reachDEFAULT_MIN_SPLIT_ROWS(8,192, the writer's row block), ormax_rowsif that is smaller. It runs before the existing sub-division of wide spans.Effect
Full scan of one file, with Arrow conversion as JNI does it. Live native bytes are measured with a counting allocator:
Tests
RepartitionStrategy):LayoutSubSplittingmerges soft boundaries and preserves shared and validity boundaries, for nullable and non-nullable structs.merge_small_spans: unit cases plus 1,000 generated cases checking endpoints, hard boundaries, exact coverage, minimum spans at retained soft boundaries, and subsequent subdivision.vortex-layoutlibrary tests; all-target, all-feature Clippy forvortex-layoutandvortex-filewith-D warnings; pinned Rust formatting; Java Spotless; full./gradlew build --no-parallel --max-workers=1including JNI and Spark checks; patch whitespace. All passed. The full Rust workspace suite was not rerun locally; Linux musl CI passed the workspace tests.Review follow-up
Not done here
🤖 Generated with Claude Code