Repository navigation
fix: spill a native sort's buffered batches in groups when their output merge does not fit - #22
Merged
Merged
Conversation
…ut merge does not fit The in-memory output merge of a sort that never spilled holds the sorted batches and the rows its cursor encodes the sort key of each run's batch into. With a multi-column key every buffered batch is a run, so these rows can outgrow what sorting frees, and the merge failed with "Additional allocation failed for ExternalSorterMerge[...]" once the sorter had filled its share of the pool, with nothing left to spill. Before that merge, estimate its memory from the batches and a sampled row encoding. If the pool cannot grant what exceeds the sorter's and the merge's reservations, spill the batches in consecutive groups whose merges fit, and merge the spill files with the multi-level merge, which already reduces its fan-in and read-ahead to the memory it gets. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.
Problem
merchants_lifecycle(em32 9/12/5) andgcs_cost_insights_v2fail on 1.1-9/1.1-10/1.1-11 withAdditional allocation failed for ExternalSorterMerge[0] ... consumer holds ~fair limit ... 0 bytes overcommitted, 10/10 task attempts.The failing path is the in-memory output merge of a sort that never spilled (not the spill-file merge, which bypasses the pool and already degrades). That merge keeps the sorted batches plus the rows
RowCursorStreamencodes each run's sort key into. With a multi-column key every buffered batch is its own run, so the rows can outgrow what sorting frees; once the sorter has filled its share there is nothing left to spill and the merge fails on a ~0.5-1.3 MB row-buffer grow (exact prod signature reproduced in a Rust test).Fix
Before the in-memory output merge, estimate its memory (sliced size of each run + sampled row-encoding bytes/row x rows of its current chunk, +25%; nothing extra for single-column field cursors). If the pool cannot grant what exceeds the sorter's and merge's reservations, spill the buffered batches in consecutive groups, each sized so its merge fits its own reservation + merge headroom + what the pool grants, then merge the spill files with the existing multi-level merge (fan-in / read-ahead / split degradation). No infallible growth past the pool is added. Healthy sorts take the same path as before.
merge_uses_row_cursormoved tostreaming_merge.rsand shared withmulti_level_merge.rs.Tests
output_merge_that_does_not_fit_spills_instead_of_failing: without the fixResourcesExhausted ... ExternalSorterMerge[0] ... 544 KB; with the fix it spills in groups, peak reserved <= pool limit, output equals the reference sort.🤖 Generated with Claude Code