Netty中的缓冲区为什么比原生NIO更高效

Netty自己的ByteBuf

ByteBuf是为了解决ByteBuffer的问题和满足网络应用程序开发人员的日常需求而设计的.
JDK中ByteBuffer的缺点:
  1. 无法动态扩容 长度是固定的,不能动态扩展和收缩,当数据大于ByteBuffer容量时,会发生索引越界异常.
  2. API使用复杂 读写的时候需要手动调用flip()和rewind()等方法,使用时需要非常谨慎的使用这些api,否则容易出现错误.
ByteBuf做了哪些增强?
  1. API操作便捷性
  2. 动态扩容
  3. 多种ByteBuf实现
  4. 内存复用机制
  5. 零拷贝机制
ByteBuf的操作三个重要属性:
  1. capacity容量
  2. readerIndex读取位置
  3. writerIndex写入位置
提供了两个指针变量来支持顺序读和写操作,分别是readerIndex和writeInDex,也就把缓冲区分成了三个部分:
0[ --已读可丢弃区域-- ]reaerIndex[ --可读区域-- ]writerIndex[ --待写区域-- ]capacity常用方法定义:
  • 随机访问索引getByte
  • 顺序读read*
  • 顺序写write*
  • 清除已读内容discardReadBytes
  • 清除缓冲区clear
  • 搜索操作
  • 标记和重置
  • 引用计数和释放
我们可以对这些api做一些测试,如下:
package io.netty.example.echo;import JAVA.util.Arrays;import io.netty.buffer.ByteBuf;import io.netty.buffer.Unpooled;/** * @author daniel * @version 1.0.0 * @date 2021/12/20 */public class ApiTest {public static void main(String[] args) {//1.创建一个非池化的ByteBuf,大小为10字节ByteBuf buf = Unpooled.buffer(10);System.out.println("原始ByteBuf为:" + buf.toString());System.out.println("1.ByteBuf中的内容为:" + Arrays.toString(buf.array()));System.out.println();//2.写入一段内容byte[] bytes = {1,2,3,4,5};buf.writeBytes(bytes);System.out.println("写入的bytes为:" + Arrays.toString(bytes));System.out.println("写入一段内容后ByteBuf为:" + buf);System.out.println("2.ByteBuf中的内容为:" + Arrays.toString(buf.array()));System.out.println();//3.读取一段内容byte b1 = buf.readByte();byte b2 = buf.readByte();System.out.println("读取的bytes为:" + Arrays.toString(new byte[]{b1, b2}));System.out.println("读取一段内容后ByteBuf为:" + buf);System.out.println("3.ByteBuf中的内容为:" + Arrays.toString(buf.array()));System.out.println();//4.将读取的内容丢弃buf.discardReadBytes();System.out.println("丢弃已读取的内容后ByteBuf为:" + buf);System.out.println("4.ByteBuf中的内容为:" + Arrays.toString(buf.array()));System.out.println();//5.清空读写指针buf.clear();System.out.println("清空读写指针后ByteBuf为:" + buf);System.out.println("5.ByteBuf中的内容为:" + Arrays.toString(buf.array()));System.out.println();//6.再次写入一段内容,比第一段内容少byte[] bytes2 = {1,2,3};buf.writeBytes(bytes2);System.out.println("再写入的bytes2为:" + Arrays.toString(bytes2));System.out.println("再写入一段内容后ByteBuf为:" + buf);System.out.println("6.ByteBuf中的内容为:" + Arrays.toString(buf.array()));System.out.println();//7.将ByteBuf清空buf.setZero(0, buf.capacity());System.out.println("内容清空后ByteBuf为:" + buf);System.out.println("7.ByteBuf中的内容为:" + Arrays.toString(buf.array()));System.out.println();//8.再次写入一段超过容量的内容byte[] bytes3 = {1,2,3,4,5,6,7,8,9,10,11};buf.writeBytes(bytes3);System.out.println("写入超量的bytes3为:" + Arrays.toString(bytes3));System.out.println("写入超量内容后ByteBuf为:" + buf);System.out.println("8.ByteBuf中的内容为:" + Arrays.toString(buf.array()));System.out.println();}}【Netty中的缓冲区为什么比原生NIO更高效】从这些api的使用中就可以体会到ByteBuf比ByteBuffer的强大之处,我们可以深入研究一下它在写入超量数据时的扩容机制,也就是buf.writeBytes(byte[])方法


    推荐阅读