dwsmith1983 commented on code in PR #6336:
URL: https://github.com/apache/datafusion-comet/pull/6336#discussion_r4380899805


##########
native/shuffle/src/writers/local/local_partition_writer.rs:
##########
@@ -245,88 +313,100 @@ impl PartitionWriter for LocalPartitionWriter {
         let write_buffer_size = self.write_buffer_size;
         let batch_size = self.batch_size;
 
-        match &mut self.data_output {
-            DataOutput::Single { writer, scratch } => {
-                // Single-partition data was already streamed via `write`, 
starting at
-                // offset 0 (already recorded in `self.offsets[0]`). Stream 
any trailing
-                // batches (normally none) without flushing; the long-lived 
writer is
-                // flushed once in `finish_all`.
-                for batch in iter.by_ref() {
-                    let batch = batch?;
-                    writer.write(
-                        &batch,
-                        scratch,
-                        &mut self.codec_context,
-                        &metrics.encode_time,
-                        &metrics.write_time,
-                    )?;
-                }
-            }
-            DataOutput::Multi {
-                output_writer,
-                shuffle_block_writer,
-                spill,
-                spill_reader,
-                recycled_buffer,
-                ..
-            } => {
-                self.offsets[pid] = output_writer.stream_position()?;
-
-                let mut flush_timer = metrics.write_time.timer();
-                spill.flush()?;
-                flush_timer.stop();
-                let ranges = spill.ranges(pid)?;
-                if !ranges.is_empty() {
-                    if spill_reader.is_none() {
-                        let path = spill.path()?.ok_or_else(|| {
-                            DataFusionError::Internal(
-                                "shuffle spill ranges recorded without a spill 
file".to_string(),
-                            )
-                        })?;
-                        *spill_reader = Some((File::open(path)?, vec![0; 
write_buffer_size]));
-                    }
-                    let (spill_file, buffer) = spill_reader.as_mut().unwrap();
-                    let mut write_timer = metrics.write_time.timer();
-                    for range in ranges {
-                        copy_spill_range(spill_file, buffer, range, 
output_writer)?;
-                    }
-                    write_timer.stop();
-                }
-
-                // Write in memory batches to output data file. Each partition 
uses its
-                // own writer so coalescing does not cross partition 
boundaries, but the
-                // scratch buffer is shared so its capacity carries over to 
the next one.
-                let mut buf_batch_writer = BufBatchWriter::new(
-                    shuffle_block_writer,
-                    output_writer,
-                    write_buffer_size,
-                    batch_size,
-                );
-                let codec_context = &mut self.codec_context;
-                let result: datafusion::common::Result<()> = (|| {
+        // Synced on every exit, errors included, so it matches what a failed 
partition left.
+        let result: datafusion::common::Result<()> = (|| {
+            match &mut self.data_output {
+                DataOutput::Single { writer, scratch } => {
+                    // Single-partition data was already streamed via `write`, 
starting at
+                    // offset 0 (already recorded in `self.offsets[0]`). 
Stream any trailing
+                    // batches (normally none) without flushing; the 
long-lived writer is
+                    // flushed once in `finish_all`.
                     for batch in iter.by_ref() {
                         let batch = batch?;
-                        buf_batch_writer.write(
+                        writer.write(
                             &batch,
-                            recycled_buffer,
-                            codec_context,
+                            scratch,
+                            &mut self.codec_context,
                             &metrics.encode_time,
                             &metrics.write_time,
                         )?;
                     }
-                    buf_batch_writer.flush(
-                        recycled_buffer,
-                        codec_context,
-                        &metrics.encode_time,
-                        &metrics.write_time,
-                    )
-                })();
-                // An errored partition must hand back a drained buffer, or 
its bytes
-                // leak into the next partition's block.
-                result.inspect_err(|_| recycled_buffer.clear())?;
+                }
+                DataOutput::Multi {
+                    output_writer,
+                    shuffle_block_writer,
+                    spill,
+                    spill_reader,
+                    recycled_buffer,
+                    ..
+                } => {
+                    self.offsets[pid] = output_writer.stream_position()?;
+
+                    let mut flush_timer = metrics.write_time.timer();
+                    spill.flush()?;
+                    flush_timer.stop();
+                    let ranges = spill.ranges(pid)?;
+                    if !ranges.is_empty() {
+                        if spill_reader.is_none() {
+                            let path = spill.path()?.ok_or_else(|| {
+                                DataFusionError::Internal(
+                                    "shuffle spill ranges recorded without a 
spill file"
+                                        .to_string(),
+                                )
+                            })?;
+                            // Open first, so a failed open leaves nothing 
charged.
+                            let spill_file = File::open(path)?;
+                            let buffer_size =
+                                
self.buffers.as_ref().map_or(write_buffer_size, |buffers| {
+                                    super::reserve_buffer(buffers, 
write_buffer_size)

Review Comment:
   The first `finish_partition` now flushes the spill file and releases its 
write buffer before anything else, then sizes the copy buffer and only then the 
data file buffer. The copy buffer serves every spilled range; the data file 
buffer matters less, because blocks of the write buffer size bypass it, so it 
is the one that falls back to 8 KiB when the pool is short. 
`output_buffers_are_sized_after_the_spill_buffer_is_released` checks the 
capacities at pools that fit two full buffers, one, and none, with identical 
output, and the last case still copies a large range through `io::copy`. 
`failed_first_partition_keeps_the_reservation_in_sync` fails a partition after 
the release and checks that the reservation still equals what the writer holds.
   



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