perf(engine): reuse immutable sub-list views when slicing paginated tables (F10)#147
Merged
Merged
Conversation
…ables A table that spans many pages is split page-by-page; each split re-sliced the shrinking tail by List.copyOf-ing its already-immutable row and row-height lists, making continuation O(rows x pages). The body-only slice now reuses the immutable sub-list views directly -- byte-identical output, O(1) per split. Warm compile allocation on a 2,500-row / 68-page table: 11,155 KB -> 9,851 KB (-11.7%, deterministic). All table layout, pagination, and visual-regression tests pass unchanged; adds TableSlicePaginationTest pinning the row-distribution invariant across chained re-slices.
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.
Finding 10 — table pagination stops re-copying the tail on every page split
A multi-page table is split page-by-page (
NodeDefinitionSupport.splitTable→TableLayoutSupport.sliceTablePreparedNode). Each split re-sliced the shrinking tail byList.copyOf-ing its row and row-height lists — even thoughresolveTableLayoutalready builds those lists immutably (List.copyOf). Because the tail is re-sliced on every continuation page, that copy made pagination O(rows × pages).The body-only slice now reuses the immutable sub-list views directly (a
subListof an immutable list is already unmodifiable, and the fragment layout is transient — emit reads individual rows into fragments, so nothing long-lived retains the view). The repeated-header path still concatenates a genuine new list and is unchanged.Before/after — deterministic allocation probe (2,500-row / 68-page table)
List.copyOfslice)AFTER min = max = 9,851 KB — fully deterministic.
Byte-identity
Same rows, same order — the slice just stops copying. Proven by:
verifygreen: 1151 tests, japicmp + architecture guards;TableSlicePaginationTestpins the invariant — a 120-row (≥3 page) table places every row on exactly one page across the chained re-slices.No public API or behaviour change.