关于Netty的ByteBuf.discardReadBytes()的坑爹描述

Posted Hello架构

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于Netty的ByteBuf.discardReadBytes()的坑爹描述相关的知识,希望对你有一定的参考价值。

Netty提供的ByteBuf提供有一个discardReadBytes()方法,许多Netty的翻译文档对该方法的描述都是用来“释放内存”,其实这是这样的描述是不正确的,还是直接看英文原版和源码更直接discardReadBytes()的底层实现,其实是System.arrayCopy(),我们首先来看一个例子:

byte[] value1 = "12aa".getBytes();

byte[] value2 = "34".getBytes();

System.arraycopy(value2, 0, value1, 2, 2);

System.out.println(new String(value1));

 

原本value1的值是“12aa”,实际输出确实“1234”,System.arrayCopy()简单来说是用来实现数组之间的复制操作,笔者用value2的值覆盖了value12个元素后的值。

 

NettydiscardReadBytes()方法也使用了System.arrayCopy()方法,但并非是用来“释放内存”,而是为了避免动态扩容产生性能损耗,典型的用时间换空间的做法。我们来看一个示例:

ByteBuf buf = Unpooled.buffer(5);

buf.writeBytes("Hello".getBytes(CharsetUtil.UTF_8));

System.out.println("capacity:" + buf.capacity());

buf.writeBytes("Cat".getBytes(CharsetUtil.UTF_8));

System.out.println("capacity:" + buf.capacity());

 

第一次输出capacity的值为5byte,而当我们继续追加数据后,由于缓冲区空间不足,ButeBuf进行了一次动态扩容,扩容后的大小为64byte。假设某些情况下,我们的内存资源是比较吃紧的,一些已经读过的字节内容希望能够废弃掉,以便于有足够的空间能够容纳新的数据,如下所示:

ByteBuf buf = Unpooled.buffer(5);

buf.writeBytes("Hello".getBytes(CharsetUtil.UTF_8));

System.out.println("capacity:" + buf.capacity());

/* 将读索引移至第5个元素上 */

buf.readerIndex(4);

buf.discardReadBytes();

buf.writeBytes("Cat".getBytes(CharsetUtil.UTF_8));

System.out.println("capacity:" + buf.capacity());

 

当我们将读索引指向数组中的第5个元素上并执行discardReadBytes()方法后,缓冲区内部会通过调用System.arrayCopy()方法实现一次数组(内存)复制,这时缓冲区的读索引会被重设为0,可读字节(5个元素)会被移动到索引为0的位置上,源0-3索引位置的数据将被“丢弃”,当继续往缓冲区写入4byte数据时,由于空间足够存放新数据,避免了动态扩容,最终capacity的值还是为5byte


以上是关于关于Netty的ByteBuf.discardReadBytes()的坑爹描述的主要内容,如果未能解决你的问题,请参考以下文章

关于Netty启动的一个疑问

关于Netty的ByteBuf.discardReadBytes()的坑爹描述

送书活动火热进行中 | 关于Netty,这本书都有!

关于TCP粘包的Netty处理的方法

[翻译]Reactor Netty参考指南 - 1.关于这个文档

Netty进阶篇二关于Buffer内存