Netty Buffer 源代码学习

467 查看

内存管理

Area

Netty 将内存分为 heap(java 堆区)和 direct(直接内存)区,heap 区依靠 java GC进行内存回收,direct 区需要显式进行释放

PoolArena 类是分区内存的基类,它有两个子类 HeapArena 和 DirectArena 分别对应 heap 区和 direct 区

Trunk

chunk 是比 area 小一级的内存分配单元,多个 chunk 按照 usage(使用率)组成chunk list,area 包含 6 个 chunk list:

// PoolArena 构造方法
q100 = new PoolChunkList<T>(null, 100, Integer.MAX_VALUE, chunkSize);
q075 = new PoolChunkList<T>(q100, 75, 100, chunkSize);
q050 = new PoolChunkList<T>(q075, 50, 100, chunkSize);
q025 = new PoolChunkList<T>(q050, 25, 75, chunkSize);
q000 = new PoolChunkList<T>(q025, 1, 50, chunkSize);
qInit = new PoolChunkList<T>(q000, Integer.MAX_VALUE, 25, chunkSize)

PoolChunkList 构造方法的第一个参数是 下一个 PoolChunkList 的引用,PoolChunList 的 prevList 方法设置 上一个 PoolChunkList:

// PoolArena 构造方法
q100.prevList(q075);
q075.prevList(q050);
q050.prevList(q025);
q025.prevList(q000);
q000.prevList(null);
qInit.prevList(qInit);

所有的 PoolChunkList 组成双向列表,qInit 是列表头。随着内存的分配和释放,PoolChunk 的使用率会发生变化,导致 PoolChunk 在这个双向列表里"流动",比如随着使用率的降低从 q075 移到 q050。

Page

page 是最小的内存分配单元,一个 chunk 里面包含多个 page,chunk 使用基于平衡二叉树的伙伴分配算法来分配和释放 page。一个 page 包含多个固定大小的内存块,并使用位图(bitmap)来跟踪这些内存块的分配和释放

内存分配

ByteBuf

ByteBuf 是 netty 对 byte[] 的封装,提供顺序和随机读写字节的功能。ByteBuf 是一个抽象类 ,它有众多的子类:

功能类(是否缓存, 内存分配方式, 是否使用 unsafe)

  • PooledHeapByteBuf

  • PooledUnsafeHeapByteBuf

  • PooledDirectByteBuf

  • PooledUnsafeDirectByteBuf

  • UnpooledHeapByteBuf

  • UnpooledUnsafeHeapByteBuf

  • UnpooledDirectByteBuf

  • UnpooledUnsafeDirectByteBuf

包装类:

  • ReadOnlyByteBufferBuf,对 idk 提供的 ByteBuffer 的只读封装

  • CompositeByteBuf, 组合多个 ByteBuf