【Netty源码解读和权威指南】第40篇:Netty内存管理深度解析——PoolChunk/PoolArena源码全剖析
2026/6/20 15:31:52
网站开发
上一篇【第39篇】Netty内存泄漏检测机制源码解析——守护ByteBuf的“生死账本“下一篇【第41篇】Netty开发HTTP服务——打造轻量级Web服务器明日更新敬请期待一、内存管理架构PooledByteBufAllocator ├── heapArenas[N] (堆内Arena数组) └── directArenas[N] (直接内存Arena数组) │ ├── PoolChunkList[6] (按使用率分6级) │ └── PoolChunk (16MB) │ ├── PoolSubpage[2048] (8KB/页) │ │ └── bitmap (按规格切割: 16B/32B/...) │ └── memoryMap (完全二叉树buddy算法) │ └── PoolThreadCache (线程缓存) ├── tinySubPageCaches[32] (512B) ├── smallSubPageCaches[4] (512B~8KB) └── normalCaches[3] (8KB~16MB)二、PoolChunkbuddy算法分配≥8KB// Chunk 16MB 2048 × 8KB pages// 使用完全二叉树管理深度11层// memoryMap: 4096个节点的数组// allocateRun(normCapacity)分配≥8KB的内存longallocateRun(intnormCapacity){intdmaxOrder-log2(normCapacity/pageSize);// 计算深度intidallocateNode(d);// 在二叉树中查找空闲节点updateParentsAlloc(id);// 更新父节点的分配状态returnid;}// memoryMap[id] depth_of_id 表示空闲// memoryMap[id] 不可用值(12) 表示已分配intallocateNode(intd){intid1;// 从根节点开始for(inti1;id;i){intleftid1;intrightleft|1;if(memoryMap[left]d){idleft;// 左子树有空闲}elseif(memoryMap[right]d){idright;// 右子树有空闲}else{return-1;// 无可用空间}}memoryMap[id]12;// 标记为已分配returnid;}三、PoolSubpageslab分配8KB// 一页8KB切成n个等大小块// 例如请求1KB → 切成8块每块1KB// 使用bitmap管理分配longallocate(){intbitmapIdxgetNextAvail();// bitmap找空闲位intqbitmapIdx6;// bitmap中的第几个longintrbitmapIdx63;// long中的第几个bitbitmap[q]|1Lr;// 标记为已分配returntoHandle(bitmapIdx);}四、分配流程请求分配1024字节 ↓ 优先查 PoolThreadCache线程缓存 ↓ 未命中 查 PoolArena ↓ 8KB? → PoolSubpage (slab分配) ↓ ≥ 8KB? → PoolChunk (buddy分配) ↓ 无可用Chunk 创建新Chunk → 分配五、内存池回收// Chunk使用率降到0% → 从活跃列表移除 → 可能被回收// 使用率变化在 q000→q025→q050→q075→q100 之间迁移// 6级ChunkList:// qInit → q000 → q025 → q050 → q075 → q100// (使用率0-25%) (25-50%) (50-75%) (75-100%)六、总结组件职责大小范围PoolThreadCache线程级缓存多种规格PoolSubpageslab小对象分配 8KBPoolChunkbuddy大对象分配8KB ~ 16MBPoolArena管理ChunkList整体协调上一篇【第39篇】Netty内存泄漏检测机制源码解析——守护ByteBuf的“生死账本“下一篇【第41篇】Netty开发HTTP服务——打造轻量级Web服务器明日更新敬请期待