jamespud opened a new pull request, #16027:
URL: https://github.com/apache/dubbo/pull/16027
- 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
Below are test code:
```java
import org.apache.dubbo.remoting.buffer.ByteBufferBackedChannelBuffer;
import org.apache.dubbo.remoting.buffer.ChannelBuffer;
import org.apache.dubbo.remoting.transport.netty4.NettyBackedChannelBuffer;
import
org.apache.dubbo.remoting.transport.netty4.NettyBackedChannelBufferOld;
import java.nio.ByteBuffer;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import org.junit.jupiter.api.Test;
public class NettyBackedChannelBufferBenchmarkTest {
private static final int BUFFER_SIZE = 1024 * 1024; // 1MB
private static final int TEST_ITERATIONS = 1000;
@Test
public void testPerformance() {
byte[] data = new byte[BUFFER_SIZE];
for (int i = 0; i < data.length; i++) {
data[i] = (byte) (i % 256);
}
ByteBuf nettyBuffer =
PooledByteBufAllocator.DEFAULT.buffer(BUFFER_SIZE);
nettyBuffer.writeBytes(data);
ChannelBuffer nettySource = new
NettyBackedChannelBuffer(nettyBuffer);
// Netty->Netty vs Netty->Other (getBytes)
double nettyToNettyGet = testGetBytes(
nettySource, new
NettyBackedChannelBuffer(PooledByteBufAllocator.DEFAULT.buffer(BUFFER_SIZE)));
double nettyToOtherGet = testGetBytes(
nettySource, new
NettyBackedChannelBufferOld(PooledByteBufAllocator.DEFAULT.buffer(BUFFER_SIZE)));
System.out.printf(
"getBytes: Netty->Netty %.2f MB/s, Netty->Other %.2f MB/s,
ratio %.2f\n",
nettyToNettyGet, nettyToOtherGet, (nettyToOtherGet > 0 ?
nettyToNettyGet / nettyToOtherGet : 0.0));
// Netty->Netty vs Netty->Other (setBytes)
double nettyToNettySet = testSetBytes(
nettySource, new
NettyBackedChannelBuffer(PooledByteBufAllocator.DEFAULT.buffer(BUFFER_SIZE)));
double nettyToOtherSet = testSetBytes(
nettySource, new
NettyBackedChannelBufferOld(PooledByteBufAllocator.DEFAULT.buffer(BUFFER_SIZE)));
System.out.printf(
"setBytes: Netty->Netty %.2f MB/s, Netty->Other %.2f MB/s,
ratio %.2f\n",
nettyToNettySet, nettyToOtherSet, (nettyToOtherSet > 0 ?
nettyToNettySet / nettyToOtherSet : 0.0));
System.out.println("-----------------------------------");
ByteBufferBackedChannelBuffer byteBufferSource =
new
ByteBufferBackedChannelBuffer(ByteBuffer.allocate(BUFFER_SIZE));
if (byteBufferSource.readableBytes() < BUFFER_SIZE) {
byteBufferSource.clear();
byteBufferSource.writeBytes(data);
}
double otherToNettyGet = testGetBytes(
byteBufferSource, new
NettyBackedChannelBuffer(PooledByteBufAllocator.DEFAULT.buffer(BUFFER_SIZE)));
double otherToOtherGet = testGetBytes(
byteBufferSource, new
NettyBackedChannelBufferOld(PooledByteBufAllocator.DEFAULT.buffer(BUFFER_SIZE)));
System.out.printf(
"getBytes: Other->Netty %.2f MB/s, Other->Other %.2f MB/s,
ratio %.2f\n",
otherToNettyGet, otherToOtherGet, (otherToOtherGet > 0 ?
otherToNettyGet / otherToOtherGet : 0.0));
double otherToNettySet = testSetBytes(
byteBufferSource, new
NettyBackedChannelBuffer(PooledByteBufAllocator.DEFAULT.buffer(BUFFER_SIZE)));
double otherToOtherSet = testSetBytes(
byteBufferSource, new
NettyBackedChannelBufferOld(PooledByteBufAllocator.DEFAULT.buffer(BUFFER_SIZE)));
System.out.printf(
"setBytes: Other->Netty %.2f MB/s, Other->Other %.2f MB/s,
ratio %.2f\n",
otherToNettySet, otherToOtherSet, (otherToOtherSet > 0 ?
otherToNettySet / otherToOtherSet : 0.0));
nettyBuffer.release();
}
private static double testGetBytes(ChannelBuffer src, ChannelBuffer
dest) {
if (src.readableBytes() < BUFFER_SIZE) {
byte[] fill = new byte[BUFFER_SIZE];
for (int i = 0; i < fill.length; i++) {
fill[i] = (byte) (i % 256);
}
src.clear();
src.writeBytes(fill);
}
for (int i = 0; i < TEST_ITERATIONS / 10; i++) {
dest.clear();
src.getBytes(0, dest, 0, BUFFER_SIZE);
}
long startTime = System.nanoTime();
for (int i = 0; i < TEST_ITERATIONS; i++) {
dest.clear();
src.getBytes(0, dest, 0, BUFFER_SIZE);
}
long endTime = System.nanoTime();
long totalTime = endTime - startTime;
dest.release();
return TEST_ITERATIONS / (totalTime / 1_000_000_000.0);
}
private static double testSetBytes(ChannelBuffer src, ChannelBuffer
dest) {
if (src.readableBytes() < BUFFER_SIZE) {
byte[] fill = new byte[BUFFER_SIZE];
for (int i = 0; i < fill.length; i++) {
fill[i] = (byte) (i % 256);
}
src.clear();
src.writeBytes(fill);
}
for (int i = 0; i < TEST_ITERATIONS / 10; i++) {
dest.clear();
dest.setBytes(0, src, 0, BUFFER_SIZE);
}
long startTime = System.nanoTime();
for (int i = 0; i < TEST_ITERATIONS; i++) {
dest.clear();
dest.setBytes(0, src, 0, BUFFER_SIZE);
}
long endTime = System.nanoTime();
long totalTime = endTime - startTime;
dest.release();
return TEST_ITERATIONS / (totalTime / 1_000_000_000.0);
}
}
```
Test output:
```plain text
getBytes: Netty->Netty 36047.87 MB/s, Netty->Other 6926.83 MB/s, ratio 5.20
setBytes: Netty->Netty 49730.58 MB/s, Netty->Other 13129.59 MB/s, ratio 3.79
-----------------------------------
getBytes: Other->Netty 53048.21 MB/s, Other->Other 46807.54 MB/s, ratio 1.13
setBytes: Other->Netty 11765.61 MB/s, Other->Other 11816.55 MB/s, ratio 1.00
```
--
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]