在netty
中发送两个字节缓冲区(header + body)的最佳方法是什么我在我们的项目中使用netty,现在我们将以下列格式发送数据
我正在搜索关于标题+正文的最快发送方式 关键是我想避免数组副本,因为正文有大量数据。
1)创建一个新的byte []并将正文复制到其中
void sendData1(ChannelHandlerContext ctx, byte[] body) {
byte[] newBuf = new byte[4+body.length];
// header
int len = body.length;
newBuf[3] = (byte) (len & 0xff);
len >>= 8;
newBuf[2] = (byte) (len & 0xff);
len >>= 8;
newBuf[1] = (byte) (len & 0xff);
len >>= 8;
newBuf[0] = (byte) len;
// body
System.arraycopy(body, 0, newBuf, 4, body.length);
final ByteBuf outBuf = Unpooled.wrappedBuffer(newBuf);
ctx.writeAndFlush(outBuf);
}
2)直接使用netty ByteBuf的写函数
void sendData2(ChannelHandlerContext ctx, byte[] body) {
final ByteBuf outBuf = ctx.alloc().buffer(4+body.length);
// header
outBuf.writeInt(body.length);
// body
outBuf.writeBytes(body);
ctx.writeAndFlush(outBuf);
}
3)设置两个netty ByteBuf并分别发送出来然后flush()
void sendData3(ChannelHandlerContext ctx, byte[] body) {
// header
final ByteBuf headBuf = ctx.alloc().buffer(4);
headBuf.writeInt(body.length);
// body
final ByteBuf bodyBuf = Unpooled.wrappedBuffer(body);
ctx.write(headBuf);
ctx.write(bodyBuf);
ctx.flush();
}
4)使用netty的CompositeByteBuf
void sendData4(ChannelHandlerContext ctx, byte[] body) {
// header
final ByteBuf headBuf = ctx.alloc().buffer(4);
headBuf.writeInt(body.length);
// body
final ByteBuf bodyBuf = Unpooled.wrappedBuffer(body);
CompositeByteBuf composite = ctx.alloc().compositeBuffer();
composite.addComponents(headBuf, bodyBuf);
ctx.writeAndFlush(composite);
}
选项1)和选项2)将进行阵列复制,我认为它们会有相同的性能吗? 选项3)我不确定它是否会进行数组复制,但它会调用ctx.write()两次,我认为这很昂贵; 选项4)我不确定它是否有效。但是我已经在netty5中尝试了它,似乎它只是把头发出去了。
您正在使用哪一个或者您有什么好的选择?
非常感谢!
答案 0 :(得分:2)
首先是标准免责声明......
性能通常归结为您的用例,软件和硬件配置。对于Netty而言,软件配置的一个重要组成部分是管道的大小以及管道中的内容将对您的写入起作用。性能至少还有两个主要组成部分:运行时间,内存(并且经常需要权衡以优化一个或另一个)。为了获得最佳的用例解决方案,我建议您运行不同的场景,看看是什么让您获得最佳性能。
接下来的一些实际观察:
ctx.write()
不一定要复制。这取决于您的管道以及正在使用的分配器。无论采用哪种方法,您都必须将数据写入通道。唯一的区别是您是复制应用程序层中的数据还是让通道直接将其写出来。您是否考虑过PooledByteBufAllocator和directBuffer?如果您的用例允许这些可能会提供一些性能优势。池化分配器意味着您只需支付Java一次自动调零缓冲区的费用,也可能导致GC活动减少。有关直接缓冲区ByteBuffer.allocate() vs. ByteBuffer.allocateDirect()的一般说明,请参阅此问题。