Skip to content

Commit aa93a6e

Browse files
committed
Fix CI failures.
1 parent 8e8f774 commit aa93a6e

2 files changed

Lines changed: 10 additions & 24 deletions

File tree

datafusion/core/tests/sql/runtime_config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ async fn test_invalid_memory_limit_when_limit_is_not_numeric() {
180180
async fn test_max_temp_directory_size_enforcement() {
181181
let ctx = SessionContext::new();
182182

183-
ctx.sql("SET datafusion.runtime.memory_limit = '1M'")
183+
ctx.sql("SET datafusion.runtime.memory_limit = '256K'")
184184
.await
185185
.unwrap()
186186
.collect()

datafusion/physical-plan/src/sorts/sort.rs

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ impl ExternalSorterMetrics {
138138
///
139139
/// When memory is exhausted, sorted runs are spilled directly to disk
140140
/// (one spill file per run — no merge needed since runs are already
141-
/// sorted). [`MultiLevelMerge`] handles the final merge from disk
141+
/// sorted). `MultiLevelMergeBuilder` handles the final merge from disk
142142
/// with dynamic fan-in.
143143
///
144144
/// ```text
@@ -169,7 +169,6 @@ impl ExternalSorterMetrics {
169169
/// pressure, chunk sizes shrink and radix sort amortizes less — at
170170
/// `batch_size` or below, the pipeline falls back to lexsort,
171171
/// matching the old per-batch sort behavior.
172-
/// ```
173172
struct ExternalSorter {
174173
// ========================================================================
175174
// PROPERTIES:
@@ -451,20 +450,10 @@ impl ExternalSorter {
451450

452451
// Determine if we must take the spill path.
453452
//
454-
// We must spill if:
455-
// 1. We already spilled during the insert phase, OR
456-
// 2. We have multiple sorted runs but merge_reservation is 0.
457-
//
458-
// Case 2 matters because the in-memory merge needs to allocate
459-
// cursor infrastructure (RowCursorStream / FieldCursorStream)
460-
// at build time, before any run data is consumed. The cursor
461-
// allocation comes from merge_reservation. If that's 0, the
462-
// pool is fully occupied by sorted run data and the cursor
463-
// can't allocate. Spilling to disk frees pool memory, and
464-
// MultiLevelMerge handles the merge with dynamic fan-in —
465-
// reading from spill files that don't hold pool memory.
466-
let must_spill = self.spilled_before()
467-
|| (self.sorted_runs.len() > 1 && self.merge_reservation.size() == 0);
453+
// We must spill if we already spilled during the insert phase.
454+
// The merge-from-disk path handles combining spill files with
455+
// any remaining in-memory runs.
456+
let must_spill = self.spilled_before();
468457

469458
if must_spill {
470459
// Spill remaining sorted runs. Since runs are already sorted,
@@ -484,13 +473,10 @@ impl ExternalSorter {
484473
.with_reservation(self.merge_reservation.take())
485474
.build()
486475
} else {
487-
// In-memory path: we have 0 runs, 1 run (no merge needed),
488-
// or multiple runs with merge_reservation > 0 providing
489-
// headroom for cursor allocation.
490-
//
491-
// Release merge_reservation back to the pool — in the
492-
// non-spill path, merge_sorted_runs allocates cursor memory
493-
// from the pool directly (freed merge_reservation bytes).
476+
// In-memory path: no prior spills. We have 0, 1, or multiple
477+
// sorted runs. Release merge_reservation (if any) back to the
478+
// pool — merge_sorted_runs allocates cursor memory from pool
479+
// headroom directly.
494480
self.merge_reservation.free();
495481
self.merge_sorted_runs(self.metrics.baseline.clone())
496482
}

0 commit comments

Comments
 (0)