Skip root transfer for byte-serialized via handler marker - #21454
Conversation
PR Reviewer Guide 🔍(Review updated until commit 6a09343)Here are some key observations to aid the review process:
|
PR Code Suggestions ✨Latest suggestions up to 6a09343 Explore these optional code suggestions:
Previous suggestionsSuggestions up to commit 6a09343
Suggestions up to commit 6a09343
Suggestions up to commit d933160
Suggestions up to commit 7565fb9
Suggestions up to commit a8e576b
|
d75f1b2 to
931a544
Compare
|
Persistent review updated to latest commit 931a544 |
|
❌ Gradle check result for 931a544: FAILURE Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change? |
|
Persistent review updated to latest commit d3c2ffd |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #21454 +/- ##
============================================
- Coverage 73.44% 73.33% -0.11%
+ Complexity 74456 74371 -85
============================================
Files 5967 5967
Lines 338232 338263 +31
Branches 48755 48761 +6
============================================
- Hits 248399 248060 -339
- Misses 70075 70402 +327
- Partials 19758 19801 +43 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
d3c2ffd to
f6d9195
Compare
PR Code Analyzer ❗AI-powered 'Code-Diff-Analyzer' found issues on commit f4b114b.
The table above displays the top 10 most important findings. Pull Requests Author(s): Please update your Pull Request according to the report above. Repository Maintainer(s): You can Thanks. |
|
Persistent review updated to latest commit f6d9195 |
f6d9195 to
60898f5
Compare
|
Persistent review updated to latest commit 60898f5 |
|
❌ Gradle check result for 60898f5: FAILURE Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change? |
|
Persistent review updated to latest commit 1313438 |
1313438 to
afd7a6b
Compare
|
Persistent review updated to latest commit afd7a6b |
afd7a6b to
64446b8
Compare
|
Persistent review updated to latest commit 64446b8 |
|
❌ Gradle check result for 64446b8: FAILURE Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change? |
64446b8 to
21eb36c
Compare
|
Persistent review updated to latest commit 336e28b |
336e28b to
af2d6ee
Compare
|
Persistent review updated to latest commit af2d6ee |
|
❕ Gradle check result for af2d6ee: UNSTABLE Please review all flaky tests that succeeded after retry and create an issue if one does not already exist to track the flaky failure. |
FlightTransportResponse.nextResponse() used to transfer the shared root into a response-owned root unconditionally. Byte-serialized responses copy bytes into Java fields inside handler.read() and don't retain the vectors, so the transfer is only needed on the native Arrow path. Split VectorStreamInput into ByteSerialized and NativeArrow subclasses, mirroring VectorStreamOutput, with two factories: - forByteSerialized: reads bytes from the shared root; FlightStream retains ownership. - forNativeArrow: transfers the shared root into a response-owned root. Dispatch is driven by the handler. Adds ArrowBatchResponseHandler, an abstract class that pins TransportResponseHandler#skipsDeserialization() to true. Handlers that read Arrow vectors directly extend it; others inherit the default false. Flight picks the factory from this bit on the registered handler. Wrappers (ContextRestoreResponseHandler, TraceableTransportResponseHandler, MetricsTrackingResponseHandler) forward skipsDeserialization() to their delegate. Robustness: - forNativeArrow closes the owned root if transferRoot throws, and rejects empty field-vector schemas. - NativeArrow.close() releases the owned root unless the response took ownership via ArrowBatchResponse's receive-side constructor (markTransferred). - ArrowBatchResponse throws with a clear message if decoded from a non-NativeArrow StreamInput. Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
Introduce ArrowAllocatorProvider — a node-level shared RootAllocator that all Arrow plugins use as parent. This ensures cross-plugin zero-copy transfers pass Arrow's AllocationManager associate check (source and target must share the same root). FlightTransport now gets its allocator from ArrowAllocatorProvider instead of creating its own RootAllocator. Also: - Rename markTransferred → claimOwnership (describes what the call site does, not what happened earlier in forNativeArrow) - Rename sharedRoot → streamRoot (names where it comes from, not a property that requires context to understand) - Improve ArrowBatchResponse javadoc: send/receive sections, allocator rules covering both sides Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
…nline transferTo - Rename ownedRoot to consumerRoot in VectorStreamInput to pair with producerRoot on send side - Rename ArrowBatchResponse field from producerRoot to batch (neutral for both send/receive) - Remove transferTo() wrapper, inline FlightUtils.transferRoot() at call site - Simplify ArrowBatchResponse javadoc: remove ArrowFlightChannel from allocator guidance Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
- Use ArrowAllocatorProvider.newChildAllocator() instead of ArrowFlightChannel.from() - Close response roots after extracting data in handlers - Move latch.countDown() to finally blocks - Update stale sharedRoot/ownedRoot references in test comments Signed-off-by: Bowen Lan <bowenlan@amazon.com> Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
The base StreamInput hook checks contiguous-buffer availability, which doesn't map onto a vector-row-backed stream. ByteSerialized's read methods throw EOFException directly when vectors are exhausted. Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
Follow the allocator contract: callers own and must close. Actions have no lifecycle hook, so long-lived allocators on actions leak at node shutdown. The Plugin class is Closeable — make the plugin own the allocator, expose it via createComponents() for Guice injection, and close it in Plugin.close(). Wrap BufferAllocator in a concrete holder class since Guice binds components to their concrete type, not to interfaces they implement. Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
- FlightTransport: rename rootAllocator -> flightAllocator (it's a child of ArrowAllocatorProvider's root, not a root itself); cap flight child at Integer.MAX_VALUE instead of Long.MAX_VALUE to keep a conservative upper bound on off-heap memory. - ArrowBatchResponse: rename field batch -> batchRoot; fold the C-data-import cross-allocator bug note back into the allocator rules (producer allocator must be long-lived; same-allocator transfer avoids an Arrow bug with foreign-backed buffers). - FlightOutboundHandler: restore the bug-encountered comment in processBatchTask explaining why the stream root must be created from the producer's allocator; guard against empty field vectors before indexing, matching the existing guard in VectorStreamInput.forNativeArrow. Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com>
d933160 to
6a09343
Compare
|
Persistent review updated to latest commit 6a09343 |
|
❌ Gradle check result for 6a09343: FAILURE Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change? |
|
Persistent review updated to latest commit 6a09343 |
|
❌ Gradle check result for 6a09343: FAILURE Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change? |
|
Persistent review updated to latest commit 6a09343 |
…-project#21454) * Skip root transfer for byte-serialized responses via handler marker FlightTransportResponse.nextResponse() used to transfer the shared root into a response-owned root unconditionally. Byte-serialized responses copy bytes into Java fields inside handler.read() and don't retain the vectors, so the transfer is only needed on the native Arrow path. --------- Signed-off-by: bowenlan-amzn <bowenlan23@gmail.com> Signed-off-by: Bowen Lan <bowenlan@amazon.com>
Description
On the receiving side of stream transport,
FlightTransportResponse.nextResponse()transfers the Flight stream root into a response-owned root on every batch — but byte-serialized responses copy bytes into Java fields via handler.read() and never touch the vectors. The transfer is wasted work on that path.This PR splits VectorStreamInput into two subclasses and let the handler decide which path to take.
flowchart LR stream["FlightStream<br/>(stream root)"] dispatch{"handler.skips<br/>Deserialization()?"} byte["ByteSerialized<br/>reads bytes from stream root"] native["NativeArrow<br/>transfers into consumer root"] stream --> dispatch dispatch -- false --> byte dispatch -- true --> nativeHandler marker
TransportResponseHandler gains a skipsDeserialization() bit (default false). ArrowBatchResponseHandler pins it to true. Wrappers forward their delegate's value:
flowchart LR M["MetricsTracking"] --> C["ContextRestore"] --> T["Traceable<br/>(optional)"] --> U["User handler"] M -. "skipsDeserialization()" .-> UOwnership lifecycle of Arrow on the Receive End
sequenceDiagram participant FS as FlightStream participant FTR as FlightTransportResponse participant VSI as VectorStreamInput.NativeArrow participant ABR as ArrowBatchResponse FTR->>FS: getRoot() FS-->>FTR: stream root FTR->>VSI: newStreamInput(streamRoot) Note over VSI: transfer to consumer FTR->>ABR: handler.read(input) ABR->>VSI: getRoot() + claimOwnership() Note over ABR: response now owns the root FTR->>VSI: close() Note over VSI: no-op (ownership claimed)Shared allocator
ArrowAllocatorProvider provides a single node-level RootAllocator so all Arrow plugins share the same root — required for zero-copy transfers to pass Arrow's AllocationManager associate check.
flowchart TD root["ArrowAllocatorProvider.ROOT"] flight["flight"] server["server"] client["client"] plugin["plugin allocators<br/>(e.g. analytics-search)"] root --> flight root --> plugin flight --> server flight --> clientWho should close the Arrow resource
Send: arrow batch is transfered from producer to flight, so flight should close
Receive: arrow batch is transfered from flight to consumer, so consumer should close
Related Issues
Resolves #[Issue number to be closed when this PR is merged]
Check List
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.