Netty的零拷贝与ByteBuf

Netty零拷贝

Netty的零拷贝完全是在用户态(Java 层面)的, 它的零拷贝更多的是偏向于 优化数据操作 这样的概念.而不是操作系统层面的用户态和核心态之间的数据拷贝。

Netty 的 零拷贝体现在如下几个个方面:

Netty 提供了 CompositeByteBuf 类, 它可以将多个 ByteBuf 合并为一个逻辑上的 ByteBuf, 避免了各个 ByteBuf 之间的拷贝.
通过 wrap 操作, 我们可以将 byte[] 数组、ByteBuf、ByteBuffer等包装成一个 Netty ByteBuf 对象, 进而避免了拷贝操作.
ByteBuf 支持 slice 操作, 因此可以将 ByteBuf分解为多个共享同一个存储区域的 ByteBuf, 避免了内存的拷贝.
通过 FileRegion 包装的FileChannel.tranferTo 实现文件传输, 可以直接将文件缓冲区的数据发送到目标 Channel, 避免了传统通过循环 write 方式导致的内存拷贝问题.

ButeBuffer

Java NIO提供ByteBuffer作为字节容器,但只有一个位置指针用于处理读写操作,每次读写时候都需要额外调用flip()和clear()方法,否则功能将会出错。查看ByteBuffer源码如下:
在这里插入图片描述
mark:调用mark()方法的话,mark值将存储当前position的值,等下次调用reset()方法时,会设定position的值为之前的标记值;
position:是下一个要被读写的元素的数组下标索引,该值会随get()和put()的调用自动更新;
limit:是缓冲区中第一个不能读写的元素的数组下标索引,也可以认为是缓冲区中实际元素的数量;
capacity:是缓冲区能够容纳元素的最大数量,这个值在缓冲区创建时被设定,而且不能够改变

四者关系如下:

0 <=mark <= position <= limit <= capacity

ByteBuffer bf = ByteBuffer.allocate(10);

创建初始化缓冲区,可以看到初始值position=0,而limit=capacity=初始化长度
在这里插入图片描述
调用flit刷新缓冲区为读模式

  bf.flip()

缓冲区有两种模式,分别是写模式和读模式,这两种模式通过使用flip方法进行模式。如上将缓冲区切换为读模式,则position变成了初值位置0,而limit变成了写模式下position位置。
在这里插入图片描述

 读取缓冲区中到内容:get()
 调用mark(),标记position位置  
 标记完position后,继续读取缓冲区区内容
 使用reset()方法可以使position回到mark存储到位置    
 调用compact()方法,清空已读取数据空间,进行数据到重新填充
 使用clear清空缓冲区

ByteBuf详解

从结构上来说,ByteBuf 由一串字节数组构成。数组中每个字节用来存放信息。
ByteBuf是Netty框架封装的数据缓冲区,区别于ByteBuffer需要有position、limit、flip等属性和操作来控制byteBuffer数据读写,Bytebuf通过两个位置指针来协助缓冲区的读写操作,分别是readIndex和writerIndex。

当从 ByteBuf 读取时,它的 readerIndex(读索引)将会根据读取的字节数递增。 同样,当写 ByteBuf 时,它的
writerIndex 也会根据写入的字节数进行递增

在这里插入图片描述
需要注意的是极限的情况是 readerIndex 刚好读到了 writerIndex 写入的地方。
如果 readerIndex 超过了 writerIndex 的时候,Netty 会抛出 IndexOutOf-BoundsException 异常。

初始化ByteBuf时,readIndex和writerIndex取值一开始是0,随着数据的写入writerIndex会增加,读取数据会使readIndex增加,但不会超过writerIndex。在读取之后0-readIndex被视为discard,调用discardReadBytes方法,释放这部分空间,作用类似于ByteBuffer的compact方法,移除无用数据,实现缓冲区的重复使用

初始化ByteBuf         ByteBuf bf= Unpooled.buffer(10,100)     
读取数据 read
写入数据 write
discardReadBytes 释放已经读取过的数据空间

相比较,Netty中的ByteBuf使用更加方便,还提供了查找操作(indexOf(int fromindex,int toIndex,byte value)、bytesBefore(Byte value))、数据复制(Derived buffers)、ByteBuffer和ByteBuf互相转化等功能更强大的方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员路同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值