上一篇【第57篇】PoolChunk内存分配源码全解析——buddy算法的工程实现
下一篇【第59篇】RecvByteBufAllocator源码解析——动态调整接收缓冲区
一、Subpage规格
一次Page(8KB)可按规格切割: 规格16B → 512块 (8KB/16B) 规格32B → 256块 规格64B → 128块 规格128B → 64块 规格256B → 32块 规格512B → 16块 规格1KB → 8块 规格2KB → 4块 规格4KB → 2块二、bitmap分配
finalclassPoolSubpage<T>{finallong[]bitmap;// 位图,每个bit代表一块longallocate(){intbitmapIdx=getNextAvail();// 找第一个0的bitintq=bitmapIdx>>>6;// bitmap[?]intr=bitmapIdx&63;// 第几位bitmap[q]|=1L<<r;// 标记为1(已分配)returntoHandle(bitmapIdx);}booleanfree(intbitmapIdx){intq=bitmapIdx>>>6;intr=bitmapIdx&63;bitmap[q]&=~(1L<<r);// 标记为0(释放)numAvail++;returnnumAvail==maxNumElems;// 全部释放则返回true}}示意图:
bitmap[0](64位):[1][0][1][0][0]...[0] ↑ ↑ 已分配 空闲 → 分配这个三、双向链表管理
// PoolArena中维护Subpage链表(按规格)PoolSubpage<T>[]tinySubpagePools;// tiny规格(<512B)PoolSubpage<T>[]smallSubpagePools;// small规格(512B~8KB)// Subpage通过prev/next组成双向链表finalclassPoolSubpage<T>{PoolSubpage<T>prev;PoolSubpage<T>next;voidaddToPool(){prev=head;next=head.next;head.next=this;next.prev=this;}}四、分配流程
请求分配256字节 ↓ 查PoolThreadCache (tiny/small缓存) ↓ miss 查Arena.tinySubpagePools/smallSubpagePools ↓ 找到对应规格的Subpage链表 查Subpage.bitmap → 找空闲位 ↓ 分配成功 ✓ ↓ 无空闲Subpage → 从Chunk分配新Page → 初始化为Subpage五、总结
| 组件 | 说明 |
|---|---|
| bitmap | 用位图管理小块分配 |
| 规格 | 16B~4KB共12种规格 |
| 双向链表 | 同规格Subpage链接在一起 |
| ThreadLocal缓存 | 优先从线程缓存获取 |
上一篇【第57篇】PoolChunk内存分配源码全解析——buddy算法的工程实现
下一篇【第59篇】RecvByteBufAllocator源码解析——动态调整接收缓冲区