Skip to content

[CELEBORN-2500] Use ArrayDeque instead of LinkedList in TransportFrameDecoder - #3893

Closed
SteNicholas wants to merge 1 commit into
apache:mainfrom
SteNicholas:CELEBORN-2500
Closed

SteNicholas wants to merge 1 commit into
apache:mainfrom
SteNicholas:CELEBORN-2500

Conversation

@SteNicholas

@SteNicholas SteNicholas commented Oct 22, 2026 •

Copy link
Copy Markdown
Member

What changes were proposed in this pull request?

Replace LinkedList<ByteBuf> with ArrayDeque<ByteBuf> for the pending input buffers in TransportFrameDecoder.

The decoder assembles incoming buffers into complete frames before decoding messages. Buffers that have not yet been consumed are kept in a FIFO queue: channelRead appends at the tail, decoding reads and removes from the head, and handlerRemoved releases any remaining buffers before clearing the queue.

ArrayDeque supports all operations used here (add, getFirst, removeFirst, iteration, and clear) with the same ordering. Frame assembly, buffer ownership, and reference-count release behavior remain unchanged.

Backport: apache/spark#58857.

Why are the changes needed?

Each incoming ByteBuf currently causes LinkedList.add to allocate a separate list node. This adds allocation and garbage-collection work to the Netty receive path even when the buffer can be consumed immediately.

ArrayDeque stores buffer references in a reusable backing array, removing the per-buffer list-node allocation while retaining efficient FIFO access. This is a small allocation optimization; its effect on end-to-end throughput has not been benchmarked.

Does this PR resolve a correctness bug?

  • Yes

Does this PR introduce any user-facing change?

  • Yes

No protocol, configuration, or API changes.

How was this patch tested?

Existing RPC integration tests passed on JDK 17: 7 tests in RpcIntegrationSuiteJ and 8 in SSLRpcIntegrationSuiteJ, with no failures or skipped tests. These exercise single and multiple RPCs, error responses, and one-way messages over plain and SSL connections.

…eDecoder

Replace the pending input buffer queue with ArrayDeque. The decoder only
uses FIFO operations, iteration, and clear, so frame decoding and buffer
release semantics remain unchanged.

LinkedList allocates a node for every incoming ByteBuf. ArrayDeque reuses
its backing array, avoiding these per-read node allocations on the Netty
receive path.

@afterincomparableyum afterincomparableyum left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@zaynt4606 zaynt4606 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@zaynt4606 zaynt4606 closed this in 924b054 Oct 23, 2026
zaynt4606 pushed a commit that referenced this pull request Oct 23, 2026
…eDecoder

### What changes were proposed in this pull request?

Replace `LinkedList<ByteBuf>` with `ArrayDeque<ByteBuf>` for the pending input buffers in `TransportFrameDecoder`.

The decoder assembles incoming buffers into complete frames before decoding messages. Buffers that have not yet been consumed are kept in a FIFO queue: `channelRead` appends at the tail, decoding reads and removes from the head, and `handlerRemoved` releases any remaining buffers before clearing the queue.

`ArrayDeque` supports all operations used here (`add`, `getFirst`, `removeFirst`, iteration, and `clear`) with the same ordering. Frame assembly, buffer ownership, and reference-count release behavior remain unchanged.

Backport: apache/spark#58857.

### Why are the changes needed?

Each incoming `ByteBuf` currently causes `LinkedList.add` to allocate a separate list node. This adds allocation and garbage-collection work to the Netty receive path even when the buffer can be consumed immediately.

`ArrayDeque` stores buffer references in a reusable backing array, removing the per-buffer list-node allocation while retaining efficient FIFO access. This is a small allocation optimization; its effect on end-to-end throughput has not been benchmarked.

### Does this PR resolve a correctness bug?

- [ ] Yes

### Does this PR introduce _any_ user-facing change?

- [ ] Yes

No protocol, configuration, or API changes.

### How was this patch tested?

Existing RPC integration tests passed on JDK 17: 7 tests in `RpcIntegrationSuiteJ` and 8 in `SSLRpcIntegrationSuiteJ`, with no failures or skipped tests. These exercise single and multiple RPCs, error responses, and one-way messages over plain and SSL connections.

Closes #3893 from SteNicholas/CELEBORN-2500.

Authored-by: Nicholas Jiang <programgeek@163.com>
Signed-off-by: zhengtao <shuaizhentao.szt@alibaba-inc.com>

AI-Contributed/Feature: 0/6
AI-Contributed/UT: 0/0

(cherry picked from commit 924b054)
Signed-off-by: zhengtao <shuaizhentao.szt@alibaba-inc.com>
@zaynt4606

Copy link
Copy Markdown
Contributor

Merge Summary:

Posted by merge_pr.py

@zaynt4606

Copy link
Copy Markdown
Contributor

Thanks @SteNicholas for the contribution!
Merged to main(v1.0.0), branch-0.7(v0.7.1).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants