使用Netty最小化内存使用的正确方法

时间:2011-11-19 06:38:33

标签: java netty

我在Netty中有两个场景,我试图最小化内存副本并优化内存使用:

(1)读取一个非常大的帧(20兆位)。

(2)读取大量非常小的帧(每帧50个咬合20兆位),以便在管道中的更高层重建为一条消息。

对于第一个场景,当我在帧的开头得到一个长度时,我扩展了FrameDecoder。不幸的是,由于我没有看到如何将长度返回到Netty(我只是指示帧是否完整),我相信Netty正在经历多个填充缓冲区,复制和重新分配周期,因此使用的内存超过了所需的内存。这里有什么我想念的吗?或者,如果我期望这种情况,我应该完全避开FrameDecoder吗?

在第二个场景中,我正在创建一个链接列表,其中包含我使用ChannelBuffers.wrappedBuffer包装的所有小帧(我可以将其包装在ChannelBufferInputStream中),但我再次使用的内存远远超出预期使用(可能是因为分配的ChannelBuffers有备用空间?)。这是使用Netty ChannelBuffers的正确方法吗?

2 个答案:

答案 0 :(得分:2)

  1. 有一种称为LengthFieldBasedFrameDecoder的帧解码器的专用版本。当你有一个带有消息长度的标题时,它很方便。它甚至可以通过给出偏移来从头部提取消息长度。

  2. 实际上,ChannelBuffers.wrappedBuffer不会创建接收数据的副本,它会根据给定的缓冲区创建复合缓冲区,因此不会复制接收到的帧数据。如果您在代码中持有复合缓冲区/自定义包装器而忘记取消,则可能发生内存泄漏。

  3. 这些是我遵循的做法,

    • 为长寿命对象分配直接缓冲区,在使用时对其进行切片。

    • 当我想将多个缓冲区加入/编码到一个大缓冲区中时。我使用ChannelBuffers.wrappedBuffer

    • 如果我有一个缓冲区并希望对它做一些事情/它的一部分,我通过在通道缓冲区实例上调用slice或slice(0,..)来制作它的片段

    • 如果我有一个通道缓冲区并且知道数据的位置很小,我总是使用getXXX方法

    • 如果我有一个通道缓冲区,在许多地方使用它来制作它的东西,总是使它可以修改,在使用时将其切片。

    注意:channelbuffer.slice不会复制数据,它会创建一个带有新读卡器的通道缓冲器。写索引。

答案 1 :(得分:0)

最后,看起来处理我的FrameDecoder问题的最好方法是在SimpleChannelUpstreamHandler之上编写我自己的。一旦我从标题确定了长度,我就创建了ChannelBuffer,其大小与长度完全匹配。这(以及其他更改)显着改善了我的应用程序的内存性能。

相关问题