本文共 1770 字,大约阅读时间需要 5 分钟。
Netty作为一个高性能的异步I/O框架,其内存管理机制至关重要。优化内存分配和管理能够显著提升应用性能和稳定性。本文将深入探讨Netty的内存分配机制,包括Page级别和SubPage级别的内存分配流程, PoolChunk的内存组织方式,以及内存回收机制。
Netty的内存管理基于Page和SubPage两种规格。Page通常为8KB(8192字节),而SubPage则为16字节。这种规格化设计使得内存管理更加高效,能够根据具体需求灵活分配内存。
Netty采用了双层缓存机制:一种是基于Page的内存缓存,另一种是基于SubPage的内存缓存。Page缓存主要用于大块内存的管理,而SubPage缓存则用于小块内存的高效分配。
在实际使用中,Page级别的内存分配通常通过以下代码实现:
PooledByteBufAllocator allocator = PooledByteBufAllocator.DEFAULT;ByteBuf byteBuf = allocator.heapBuffer(8192); // 分配8192B内存byteBuf.release();
尝试在现有的PoolChunk上分配
PoolArena中的PoolChunkList通过双向链表连接,每个PoolChunkList代表一种内存使用率的池。PoolArena的allocateNormal()方法会尝试从各个PoolChunkList中获取可用的PoolChunk。创建一个PoolChunk并进行内存分配
如果无法从现有PoolChunk中获取,PoolArena会调用newChunk()方法创建一个新的PoolChunk,并调用其allocateRun()方法进行内存分配。初始化PooledByteBuf对象
PoolChunk的initBuf()方法会根据分配的内存handle初始化PooledByteBuf对象,设置其内存映射和偏移量。将新建的PoolChunk添加到PoolChunkList中
PoolChunk会被添加到PoolArena的qInit PoolChunkList中,等待下次分配使用。SubPage级别的内存分配通常通过以下代码实现:
PooledByteBufAllocator allocator = PooledByteBufAllocator.DEFAULT;ByteBuf byteBuf = allocator.directBuffer(16); // 分配16B内存byteBuf.release();
定位一个SubPage对象
PoolArena的findSubpagePoolHead()方法会根据内存大小找到对应的SubPage池。初始化SubPage对象
如果SubPage池中没有可用的SubPage,会创建一个新的PoolSubpage对象,并初始化其位图和内存映射。调用SubPage的allocate()方法进行分配
PoolSubpage的allocate()方法会从位图中寻找未使用的SubPage,并返回对应的handle。当ByteBuf被释放时,PooledByteBuf的deallocate()方法会清空相关handle和内存映射,并调用PoolArena的free()方法。
PoolArena的freeChunk()方法会将释放的内存区段添加到缓存,并标记为未使用。
Page级别的内存管理通过二叉树结构标记内存为未使用,而SubPage级别则通过位图标记。
PooledByteBuf对象在释放后不会立即销毁,而是会被添加到对象池中以供复用。这种机制减少了GC压力,提升了性能。
转载地址:http://tvcfk.baihongyu.com/