jayzhan211 commented on PR #24923:
URL: https://github.com/apache/datafusion/pull/24923#issuecomment-5620074706

   The spill loop turns a memory shortfall into a hard failure, where the old 
code
   deliberately did not:
   
   ```rust
   // before
   let reservation_failed = self.reservation.try_grow(sorted_size).is_err();
   // Even if the reservation is not enough, the batch is already in
   // memory, so it's okay to combine it with previously sorted batches
   globally_sorted_batches.push(batch);
   if reservation_failed { self.consume_and_spill_append(...)?; }
   
   // after (sort.rs:517)
   let workspace = self.merge_pool.borrow(sorted_size);
   self.reservation.try_grow(sorted_size - workspace.size())?;   // <-- new 
failure path
   ```
   
   That old comment is still true and the new code contradicts it. At this 
point the
   batch was just produced by `sorted_stream.next()`, so it is *already 
resident*.
   Returning `ResourcesExhausted` reclaims nothing — it only kills a query that 
would
   otherwise have completed. Refusing an allocation is the right call when 
refusing
   prevents it; here it doesn't.
   
   This is a real regression, not a hypothetical: the PR relaxes an existing 
test to
   keep it green —
   
   ```diff
   -  .with_sort_spill_reservation_bytes(1),
   +  .with_sort_spill_reservation_bytes(spill_workspace),
   -  .with_memory_limit(batches_memory, 1.0)
   +  .with_memory_limit(batches_memory + spill_workspace, 1.0)
   ```
   
   — and `test_spill_output_respects_memory_limit` then asserts that the *old*
   configuration now yields `ResourcesExhausted`. Users running a tight
   `sort_spill_reservation_bytes`, or sorting wide `Utf8View`/string batches 
where one
   output batch exceeds the remaining merge workspace, get a new OOM on a 
workload
   that spilled fine before.
   
   Please keep the workspace-borrow optimization but stop propagating the 
shortfall:
   
   ```diff
   -            let spill_workspace = match 
self.reservation.try_grow(sorted_size) {
   -                Ok(()) => None,
   -                Err(_) => {
   -                    let workspace = self.merge_pool.borrow(sorted_size);
   -                    self.reservation.try_grow(sorted_size - 
workspace.size())?;
   -                    Some(workspace)
   -                }
   -            };
   +            let spill_workspace = match 
self.reservation.try_grow(sorted_size) {
   +                Ok(()) => None,
   +                Err(_) => {
   +                    // Reuse already-reserved workspace where we can.
   +                    let workspace = self.merge_pool.borrow(sorted_size);
   +                    let remainder = sorted_size - workspace.size();
   +                    // The batch is already in memory: failing here would 
not
   +                    // reclaim it, so record the usage and spill it 
immediately.
   +                    if self.reservation.try_grow(remainder).is_err() {
   +                        self.reservation.grow(remainder);
   +                    }
   +                    Some(workspace)
   +                }
   +            };
   ```
   
   With that, `test_spill_output_respects_memory_limit` should be dropped and 
the two
   config changes in
   
`should_return_stream_with_batches_in_the_requested_size_and_update_metrics_when_having_to_spill`
   reverted. If you believe the strict behaviour is genuinely the one we want, 
it needs
   to be called out in the PR description and in the upgrade guide as a breaking
   behavioural change — it shouldn't land as a side effect of adding an async 
writer API.


-- 
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