This is an automated email from the ASF dual-hosted git repository.
zrlw pushed a commit to branch 3.3
in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/3.3 by this push:
new f5d6436fae Optimize NettyBackedChannelBuffer for direct buffer
transfer (#16027)
f5d6436fae is described below
commit f5d6436fae851c577fcf2eb1aaab543e92acf9b4
Author: Wenli Tian <[email protected]>
AuthorDate: Wed Jan 28 14:42:58 2026 +0800
Optimize NettyBackedChannelBuffer for direct buffer transfer (#16027)
* Optimize NettyBackedChannelBuffer for direct buffer transfer
- Optimize getBytes/setBytes/readBytes/writeBytes methods
- Avoid intermediate byte array copy when source/destination is
NettyBackedChannelBuffer
- Directly use Netty's ByteBuf transfer capabilities
- Add fallback to intermediate array copy for other ChannelBuffer
implementations
- Improve performance by 4-5x for Netty-to-Netty buffer transfers
* Add tests for NettyBackedChannelBuffer
* Format code
* Update
dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/NettyBackedChannelBufferTest.java
Co-authored-by: Copilot <[email protected]>
---------
Co-authored-by: Copilot <[email protected]>
Co-authored-by: zrlw <[email protected]>
---
.../transport/netty4/NettyBackedChannelBuffer.java | 52 +++++++++++++++-------
.../netty4/NettyBackedChannelBufferTest.java | 52 ++++++++++++++++++++++
2 files changed, 88 insertions(+), 16 deletions(-)
diff --git
a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyBackedChannelBuffer.java
b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyBackedChannelBuffer.java
index d0fb5f2753..d51cb21dd9 100644
---
a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyBackedChannelBuffer.java
+++
b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyBackedChannelBuffer.java
@@ -71,10 +71,15 @@ public class NettyBackedChannelBuffer implements
ChannelBuffer {
@Override
public void getBytes(int index, ChannelBuffer dst, int dstIndex, int
length) {
- // careful
- byte[] data = new byte[length];
- buffer.getBytes(index, data, 0, length);
- dst.setBytes(dstIndex, data, 0, length);
+ // use Netty ByteBuf
+ if (dst instanceof NettyBackedChannelBuffer) {
+ NettyBackedChannelBuffer nettyDst = (NettyBackedChannelBuffer) dst;
+ buffer.getBytes(index, nettyDst.buffer, dstIndex, length);
+ } else {
+ byte[] data = new byte[length];
+ buffer.getBytes(index, data, 0, length);
+ dst.setBytes(dstIndex, data, 0, length);
+ }
}
@Override
@@ -107,10 +112,15 @@ public class NettyBackedChannelBuffer implements
ChannelBuffer {
if (length > src.readableBytes()) {
throw new IndexOutOfBoundsException();
}
- // careful
- byte[] data = new byte[length];
- src.getBytes(srcIndex, data, 0, length);
- setBytes(index, data, 0, length);
+ // use Netty ByteBuf
+ if (src instanceof NettyBackedChannelBuffer) {
+ NettyBackedChannelBuffer nettySrc = (NettyBackedChannelBuffer) src;
+ buffer.setBytes(index, nettySrc.buffer, srcIndex, length);
+ } else {
+ byte[] data = new byte[length];
+ src.getBytes(srcIndex, data, 0, length);
+ setBytes(index, data, 0, length);
+ }
}
@Override
@@ -239,13 +249,18 @@ public class NettyBackedChannelBuffer implements
ChannelBuffer {
@Override
public void readBytes(ChannelBuffer dst, int dstIndex, int length) {
- // careful
if (readableBytes() < length) {
throw new IndexOutOfBoundsException();
}
- byte[] data = new byte[length];
- buffer.readBytes(data, 0, length);
- dst.setBytes(dstIndex, data, 0, length);
+ // use Netty ByteBuf
+ if (dst instanceof NettyBackedChannelBuffer) {
+ NettyBackedChannelBuffer nettyDst = (NettyBackedChannelBuffer) dst;
+ buffer.readBytes(nettyDst.buffer, dstIndex, length);
+ } else {
+ byte[] data = new byte[length];
+ buffer.readBytes(data, 0, length);
+ dst.setBytes(dstIndex, data, 0, length);
+ }
}
@Override
@@ -362,10 +377,15 @@ public class NettyBackedChannelBuffer implements
ChannelBuffer {
@Override
public void writeBytes(ChannelBuffer src, int srcIndex, int length) {
- // careful
- byte[] data = new byte[length];
- src.getBytes(srcIndex, data, 0, length);
- writeBytes(data, 0, length);
+ // use Netty ByteBuf
+ if (src instanceof NettyBackedChannelBuffer) {
+ NettyBackedChannelBuffer nettySrc = (NettyBackedChannelBuffer) src;
+ buffer.writeBytes(nettySrc.buffer, srcIndex, length);
+ } else {
+ byte[] data = new byte[length];
+ src.getBytes(srcIndex, data, 0, length);
+ writeBytes(data, 0, length);
+ }
}
@Override
diff --git
a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/NettyBackedChannelBufferTest.java
b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/NettyBackedChannelBufferTest.java
index c2224e1994..2ed7fa66bc 100644
---
a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/NettyBackedChannelBufferTest.java
+++
b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/NettyBackedChannelBufferTest.java
@@ -18,11 +18,13 @@ package org.apache.dubbo.remoting.transport.netty4;
import org.apache.dubbo.remoting.buffer.ChannelBuffer;
+import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
class NettyBackedChannelBufferTest {
@@ -60,4 +62,54 @@ class NettyBackedChannelBufferTest {
assertEquals(1, actual[0]);
assertEquals(2, actual[1]);
}
+
+ @Test
+ void testBufferTransfer_directToDirect() {
+ ByteBuf srcDirect = Unpooled.directBuffer(4);
+ ByteBuf dstDirect = Unpooled.directBuffer(4);
+
+ try {
+ ChannelBuffer source = new NettyBackedChannelBuffer(srcDirect);
+ ChannelBuffer target = new NettyBackedChannelBuffer(dstDirect);
+
+ byte[] data = {10, 20, 30, 40};
+ source.writeBytes(data);
+
+ target.setBytes(0, source, 0, 4);
+
+ byte[] actual = new byte[4];
+ target.getBytes(0, actual);
+
+ assertArrayEquals(data, actual);
+ assertEquals(0, target.readerIndex(), "setBytes should not move
readerIndex");
+ } finally {
+ srcDirect.release();
+ dstDirect.release();
+ }
+ }
+
+ @Test
+ void testReadBytes_directBuffer() {
+ byte[] data = {1, 2, 3, 4};
+ buffer.writeBytes(data);
+
+ byte[] actual = new byte[4];
+ buffer.readBytes(actual);
+
+ assertArrayEquals(data, actual);
+ assertEquals(4, buffer.readerIndex());
+ }
+
+ @Test
+ void testGetBytes_directBuffer_shouldNotMoveIndex() {
+ buffer.writeBytes(new byte[] {5, 6, 7, 8});
+
+ int before = buffer.readerIndex();
+
+ byte[] actual = new byte[2];
+ buffer.getBytes(1, actual);
+
+ assertEquals(before, buffer.readerIndex());
+ assertArrayEquals(new byte[] {6, 7}, actual);
+ }
}