项目整体架构
高并发内存池通常采用分层设计,主要分为三部分:
- 线程缓存(ThreadCache):每个线程独有,用于分配小于 256KB 的内存。申请时无需加锁,独享特性极大提升了并发性能。
- 中心缓存(CentralCache):所有线程共享。ThreadCache 按需从中获取对象,同时也负责回收 ThreadCache 的对象以均衡内存分配。存在竞争,取内存时需加桶锁,但竞争不激烈。
- 页缓存(PageCache):位于 CentralCache 上层,以页为单位存储。当 CentralCache 无对象时,从其分配 page 并切割;同时负责回收符合条件的 span 对象并合并相邻页,缓解内存碎片。
核心挑战
在设计过程中主要关注三个问题:
- 性能问题:减少系统调用和锁开销。
- 多线程锁竞争:通过线程本地化降低冲突。
- 内存碎片:通过分级管理和对齐策略优化空间利用率。
ThreadCache 设计思路
ThreadCache 采用哈希桶结构,每个桶是一个按大小映射的自由链表。每个线程拥有独立的 ThreadCache 对象,使得对象获取与释放均为无锁操作。
虽然这种按对齐数排布的方式缓解了外碎片,但仍需注意内碎片问题。当前实现主要包含两个核心功能:申请与释放内存。
- 申请内存:请求 ≤256KB 内存时,先查找线程本地的 ThreadCache。根据大小计算自由链表下标 i,若
_freeLists[i]有对象则直接返回;若为空,则向 CentralCache 批量获取后放入链表再取出。 - 释放内存:释放 <256KB 内存时,放回 ThreadCache。根据大小计算桶位置 i,将对象推入
_freeLists[i]。若链表过长,则回收部分对象至 CentralCache。
代码实现细节
FreeList 设计
FreeList 支持删除(获取内存块)和插入(归还内存块)。采用定长内存池设计的去前指针方式保存下一个地址。该模块通用性强,后续 CentralCache 也会复用,因此置于公共类中。
class FreeList {
public:
// 头插:将对象加入空闲链表
void Push(void* ptr) {
assert(ptr);
*(void**)ptr = _freelist;
_freelist = ptr;
}
// 头删:从空闲链表取出对象
void* Pop() {
assert(_freelist);
void* next = *(void**)_freelist;
void* obj = _freelist;
_freelist = next;
return obj;
}
{
_freelist == ;
}
:
* _freelist = ;
};


