Netty缓冲区动态扩容

    **Netty简述**

    netty 是 java的一个io框架, 它简化了nio编程,提高了io的性能和可靠性,是服务端常用的框架之一,在大数据系统中也是很常见的一个框架。
    官方说明中,netty 主要提供了创建私有协议的解决方案。
    **缓冲区**

    io 编程中少不了对缓冲区的操作,缓冲区,就是一片连续的内存地址空间,也就是数组。数据通过流传输的效率低下,通过缓冲区就可以实现块传输。
    **ByteBuf**

    java nio库中已经存在了一个Buffer类,但是操作起来容易出错,每次读取都需要做flip操作,且功能有限,动态扩张等有用的特性,需要自己编程实现。
    netty提供了一个新的缓冲类实现:ByteBuf解决了上述问题。
    ByteBuf 有两个指针,一个读指针,一个写指针,它的设计如下: 

这里写图片描述

     当需要往缓冲区写数据时,writerIndex向前移动,当需要读数据时,readerIndex向前移动,读的位置始终不能超过写的位置。
     当写入了y份数据,读取了x份数据后,缓冲区将出现一部分discard 区域 。这种情况出现在粘包的情况,一次数据流传送中包含了多个数据包,前面的流包含的若干数据包已经被解析,后面的流继续写入。其状态图如下:

这里写图片描述

    **缓冲区空间不足时**

    这时候如果数据继续写入缓冲区,而缓存区的writable区间已经被判断空间不足,那就有两个方法可以解决:

    **1、动态扩展缓冲区,由ByteBuf 实现,用户无感知。**

    动态扩展缓冲区的原理,是新建一个更大的缓冲区,把在原来缓冲区的内容复制到新的缓冲区,然后就有更大的空间可以写入了。中间涉及内存的分配和内存复制,所以扩容的成本较高。
    netty缓存扩容的策略一方面要让扩容能满足后面写入的需求,不能扩容之后,马上缓冲区又被填满,又需要再一次的扩容。另一方面不能一次性扩容太多,导致内存浪费。所以一般是先倍增,再步增,举个例子,原来缓存区1M,扩容到2M,再扩容到4M,再扩容到8M,如果再继续倍增,那扩容的内存就太多了,之后就采取每次扩容4M的方式,扩容到12M,再扩容到16M。

    **2、重用discard 区域,需要调用discardReadBytes方法。**

    重用discard 区域的原理是将readable区域复制到前面,以0为起始坐标,然后重置readerIndex和writerIndex,当然还有这里没提到的标记指针。这里需要一次内存复制,还是会消耗额外的性能。重用后的缓冲区如下所示:

![这里写图片描述](https://img-blog.csdn.net/20151229094413353)
    **netty缓冲区使用**

    netty的缓存区设计不仅可以用到io上,再我们java编程的过程中需要用到缓冲区的地方都可以使用。
    一般io编程使用直接内存的缓冲区,而其他操作可以使用堆缓冲区。
    netty 包中还有缓冲区池的实现,让缓冲区可以得到重用,类图如下(图出自netty权威指南):

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值