Ma77Ball opened a new issue, #8673: URL: https://github.com/apache/texera/issues/8673
### Task Summary > **In one sentence:** columnar execution processes a whole batch (~10k rows) per DP-thread step, so pause, breakpoints, and backpressure land at batch boundaries instead of per row like the row path; this task restores fine-grained (near per-row) control by making columnar operators resumable mid-batch. **Background.** The opt-in columnar (Apache Arrow) path (see #8556, discussion #8571) preserves Amber's pipelining: operators stay concurrent actors, batches stream under credit-based backpressure (drained one batch per DP-loop step), and blocking edges are unchanged. But it coarsens one thing. The row path yields to control messages between individual tuples (`outputOneTuple` / `inputManager.getNextTuple`), while the columnar path runs an entire batch in a single DP step (`processColumnarBatch`, `emitOneColumnarBatch`). So a pause, breakpoint, or backpressure check can only land between batches, not mid-batch. For a debuggability-first engine that is a real regression in control granularity. **What was measured (why this is worth doing, and cheap).** A standalone 20M-row filter loop, JDK 17, x86, monotonic clock: | Filter loop over 20M ints | Time | vs no-check | | --- | --- | --- | | raw `int[]`, check every row | 20.1 ms | 1.00x | | Arrow `IntVector`, no check | 92.2 ms | 1.00x | | Arrow `IntVector`, check every row | 92.8 ms | 1.01x | | Arrow `IntVector`, check every 512 (chunked) | 126.3 ms | 1.37x (slower) | - A `volatile` pause-flag check **every row costs ~1%**. On x86 a volatile read is a cached load (fences are only for writes) and the never-taken branch predicts perfectly, so the "per-row check kills vectorization" intuition does not hold on the JVM. - **Chunking (checking every K rows via a nested loop) was 37% slower** on the Arrow path, a JIT artifact where the nested loop loses the bounds-check elimination the flat loop keeps. So the correct shape is a flat loop with a per-row check, not chunking. The per-row check is essentially free; the work is the resumability plumbing, not the check. ### Proposed solution / design 1. **Per-row pause check** in the columnar operator loops (filter mask, decode-into-state, gather), kept as a flat loop (no chunking). 2. **Resumable columnar processing:** the columnar entry point returns partial progress plus a row cursor (or accepts a start cursor), so an operator can stop mid-batch and be re-entered where it left off. 3. **DP-loop cooperative yield:** on a pause or backpressure signal mid-batch, save the cursor, return to the DP main loop (input selection, control handling, backpressure check), and resume the same batch on the next step, exactly as the row path already advances a cursor through a batch tuple by tuple. 4. **Keep checkpoints at batch boundaries.** Pause is cursor-based and may be mid-batch, but epoch/marker checkpoints and reconfiguration stay aligned to message boundaries so replay and exactly-once are unaffected. 5. **Make the check frequency a tunable** (default per-row on x86). On weak-memory architectures (ARM) a volatile read may compile to a fenced load and not be free, so allow checking every N rows. **Scope.** This is an engine change (the DP main loop plus the columnar operator contract), not a drive-by, and should land after the columnar series (#8556) merges. Related discussion: #8571. ### Task Type - [x] Performance -- 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]
