sunchao commented on code in PR #25428:
URL: https://github.com/apache/datafusion/pull/25428#discussion_r4112144194


##########
datafusion/physical-plan/src/sorts/multi_level_merge.rs:
##########
@@ -393,6 +411,35 @@ impl MultiLevelMergeBuilder {
                     }
                 };
 
+                if self.size_intermediate_merges
+                    && self.sorted_streams.is_empty()
+                    && !self.sorted_spill_files.is_empty()
+                {
+                    // If one intermediate merge can leave a final pass with 
the
+                    // admitted fan-in, merge only the runs needed to get 
there.
+                    // Keep the admitted reservation so sizing does not change

Review Comment:
   Fixed in 
[78c4b7b](https://github.com/apache/datafusion/commit/78c4b7bdb05df36583f6a2f81d2bc6098fd34030).
 A trimmed pass now keeps the existing buffer reservation in the builder 
through intermediate EOF and spill completion, then transfers it to the next 
admission.
   
   There is one additional constraint: ordinary admission initially requests 
buffers **plus equal replay headroom**, then releases the headroom. Retaining 
the buffer grant alone therefore cannot secure the original `k` inputs. The 
sizing calculation now budgets final buffers and headroom within that existing 
grant, without reserving extra bytes. With eight full runs and initial fan-in 
seven, it merges six and leaves three for final replay; nine runs now keep the 
ordinary seven-input selection. The existing width guards remain; a wider 
variable-width output can still change the subsequent budget.
   
   The competing-consumer test reproduces your nine-run case on the previous 
head: 1,152 versus 896 rewritten rows at subsequent fan-in three, and 2,304 
versus 1,152 at fan-in two. Both replay-headroom release and intermediate EOF 
reproduce it. The fix passes both boundaries; the eight-run case still improves 
from 896 to 768 rows. Tests also check exact ordered output and 
reservation/file cleanup, including dropping the intermediate stream and 
builder.
   
   I checked the earlier 64 MiB trace too: all four trims immediately precede 
final 15-input merges. The exceptional builder initially admitted nine inputs 
without trimming, accounting for its additional merge. The reason that initial 
admission stopped at nine was not logged, so that trace cannot establish its 
cause.
   
   Both optional builder arguments now match, and I clarified the final-replay 
docs. Validation passed: 12,172 Rust tests, all 524 SQL files, strict clippy, 
formatting, and full repository lint/docs. The description now contains fresh 
exact-base/current-head results: traced rewrites decrease 2.24% at 40 MiB and 
23.00% at 56 MiB, with all actual trims reaching final replay. It also retains 
the adverse diagnostic counters and variable timings; those timings do not 
reliably quantify a latency improvement.
   



##########
datafusion/physical-plan/src/sorts/multi_level_merge.rs:
##########
@@ -985,6 +1033,148 @@ mod tests {
         )
     }
 
+    #[rstest::rstest]
+    #[case::full_batches(9, 128, 3)]
+    #[case::unchanged_selection(13, 128, 7)]
+    #[case::short_batches(9, 64, 7)]
+    #[tokio::test]
+    async fn intermediate_merge_sizing_preserves_final_output(

Review Comment:
   Added in 
[78c4b7b](https://github.com/apache/datafusion/commit/78c4b7bdb05df36583f6a2f81d2bc6098fd34030):
 a pool wrapper with a real competing reservation, triggered by `shrink` at 
either replay-headroom release or intermediate EOF. Eight cases cover 
eight/nine full runs and subsequent fan-in two/three, comparing sized and 
ordinary intermediate row writes and exact sorted values. The four nine-run 
cases fail on the previous head and pass with the fix. A separate builder-drop 
case checks retained-reservation lifetime and cleanup. All nine cases passed in 
the full workspace run.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to