parthchandra opened a new issue, #7271:
URL: https://github.com/apache/datafusion-comet/issues/7271

   Part of #7267.
   
   ## Problem
   
   arrow's `BatchCoalescer` (`arrow-select/src/coalesce.rs`, 59.3.1) builds 
output
   batches up to a target row count. It has no byte limit.
   `biggest_coalesce_batch_size` (`coalesce.rs:164, 210`, applied at 
`:452-470`) is a
   row-count pass-through threshold, not a cap: larger input batches skip 
merging.
   
   For `Utf8`/`Binary` columns it buffers input slices in 
`GenericInProgressArray` and
   calls `concat` when the target is reached (`coalesce/generic.rs:94-106`). If 
those
   rows hold more than 2 GiB, `concat` fails with `OffsetOverflowError`. Before 
failing,
   `concat` also reserves the full output buffer, so peak memory is about twice 
the
   buffered data.
   
   DataFusion's `LimitedBatchCoalescer` wraps it with the pass-through 
threshold set
   to half the target (`coalesce/mod.rs:63-64`). It is used by `FilterExec`,
   `CoalesceBatchesExec`, `RepartitionExec` and the hash join output stream
   (`joins/hash_join/stream.rs:493`). The raw `BatchCoalescer` is used by 
sort-merge
   join (`materializing_stream.rs:417, 520, 574, 578`), nested loop join 
(`:1499`) and
   TopK. Comet's shuffle writer uses it directly (`buf_batch_writer.rs:133`).
   
   Nested types overflow the same way: list, map and struct `concat` recurse 
into
   `concat_bytes` (`concat.rs:399, 464, 553-558`). The over-2 GiB buffer is 
reserved
   before the error and is not tracked by the DataFusion memory pool.
   
   Even with the correct batch size (sub-issue 1), the default of 8192 rows 
overflows
   when values average more than ~256 KB.
   
   ## Proposed fix
   
   arrow-rs:
   - Add an optional byte target, for example 
`with_target_batch_bytes(Option<usize>)`.
   - Before buffering a batch, if the buffered bytes of any `Utf8`/`Binary` 
column,
     including ones nested inside lists, maps and structs, plus the incoming 
bytes would
     pass the target (capped at i32::MAX), finish the current output batch 
first. If one
     input batch alone is over the target, slice it.
   - View types and primitive types are unaffected, or can use the same budget 
for
     memory reasons.
   
   DataFusion:
   - Pass the byte target through `LimitedBatchCoalescer` and expose it on
     `FilterExec` (and any other operator using the coalescer), with a session 
config
     default.
   
   Comet:
   - Set the byte target from a Comet config, default about 1 GiB.
   - Use it in the shuffle writer's coalescer (sub-issue 2).
   
   ## Tests
   
   - arrow-rs unit tests with a small byte target: outputs never exceed it; row 
order
     and content are unchanged; an input batch over the target is sliced.
   - DataFusion `FilterExec` test with a small byte target.
   - Comet test with a small configured target and a binary column, compared 
with Spark.
   
   ## Notes
   
   - Before filing upstream, check arrow-rs #7764 and #10799. Recent benchmark 
work
     (#10797) points to a specialized Utf8/Binary in-progress array that would 
replace
     the generic concat path; a byte target may fit there.
   - Upstream first, then bump arrow and DataFusion in Comet. Comet's interim
     workaround is sub-issue 1 plus a lower `spark.comet.batchSize`.
   


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