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

   Following up on PR #5513 (part of #5352). I was reading through the new 
byte-admission code and found that the two new configs cannot both hold at 
their shipped defaults, and that the consequence for a large row is a failed 
job rather than a slow one.
   
   `spark.comet.shuffle.rss.maxFrameBytes` defaults to 64 MiB and 
`spark.comet.shuffle.rss.maxInFlightBytes` defaults to 256 MiB. In 
`RssPartitionWriter::push_batch_within_limit`, `admitted_frame_limit` is 
computed as `(reservation_limit - ipc_scratch) / 3`, and `ipc_scratch` already 
charges `original_size * 4`. So admitting a frame of `S` bytes needs roughly 
`7S` of the executor-wide budget, which means the largest admissible row at the 
defaults is about 36 MiB. The configured 64 MiB maximum is not reachable.
   
   I reproduced the cutover with a small test driving the real Rust writer, one 
`Utf8` column, one row per batch, `maxFrameBytes` set to 64 MiB and 
`maxInFlightBytes` set to 256 MiB:
   
   ```
   row= 30 MiB -> PUSHED
   row= 34 MiB -> PUSHED
   row= 36 MiB -> PUSHED
   row= 38 MiB -> FAILED: Remote shuffle frame exceeds its configured maximum: 
a single row exceeds 36346226 bytes
   row= 50 MiB -> FAILED: Remote shuffle frame exceeds its configured maximum: 
a single row exceeds 19569010 bytes
   row= 63 MiB -> FAILED: Remote shuffle frame exceeds its configured maximum: 
a single row exceeds 1393693 bytes
   ```
   
   The failure itself worries me more than the accounting. `push_split_batch` 
halves rows and bottoms out at a single row, so a row above the effective cap 
can never be pushed at all. Spark supports strings and arrays up to 2 GiB, and 
both local Comet shuffle and stock Celeborn shuffle handle a 70 MiB row without 
complaint, so enabling native Celeborn shuffle converts a query that works 
today into one that fails.
   
   It also fails after doing damage. With a batch holding one small row and one 
70 MiB row, the small row's frame was already pushed to Celeborn before the 
error:
   
   ```
   result=Err("Remote shuffle frame for a single row and encoding workspace 
exceed the byte
   admission budget of 268435456 bytes") frames_pushed=1 bytes=540
   ```
   
   Because `CelebornShufflePusherFactory.rejectRetriedAttempt` throws 
`FetchFailedException` for every attempt with `attemptNumber > 0`, each failure 
costs a full map-stage rerun, and the rerun produces the same batch. That 
terminates at `spark.stage.maxConsecutiveAttempts`, so the user sees four full 
stage reruns and then a failed job.
   
   A few questions on how to resolve this. Should the two defaults be made 
consistent, either by raising the default `maxInFlightBytes` to roughly seven 
times `maxFrameBytes` or by validating the pair at config time so an 
unreachable combination fails at startup instead of mid-stage? And should a row 
that cannot fit fall back to ordinary Spark shuffle for that stage rather than 
failing the query?
   
   Separately, the error messages are hard to act on. For a 63 MiB row the 
message reports `a single row exceeds 1393693 bytes`, which is a derived 
residual rather than any value the user configured. Naming 
`spark.comet.shuffle.rss.maxInFlightBytes` and the multiple it needs would make 
this diagnosable from a log line.
   


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