C++ 高并发内存池实战:ThreadCache 设计与实现
一、整体架构设计
高并发内存池通常分为三个层级,它们之间相互协作以平衡性能与资源管理:
- 线程缓存(ThreadCache):每个线程独享,用于分配小于 256KB 的内存。由于是线程私有,申请和释放过程无需加锁,极大提升了并发效率。
- 中心缓存(CentralCache):所有线程共享。当 ThreadCache 空间不足时向其申请,同时也负责回收 ThreadCache 中闲置的对象以均衡负载。因存在竞争,获取对象时需加桶锁,但竞争相对温和。
- 页缓存(PageCache):位于 CentralCache 上层,以页为单位存储。当 CentralCache 无可用对象时,从 PageCache 分配页面并切割使用;同时负责合并相邻页以缓解内存碎片。
核心挑战:在高并发场景下,需重点解决性能瓶颈、多线程锁竞争以及内存碎片问题。
二、ThreadCache 核心设计
1. 设计思想
ThreadCache 采用哈希桶结构,每个桶对应一个按大小映射的自由链表。每个线程持有一个独立的 ThreadCache 实例,确保对象获取与释放均为无锁操作。
虽然这种按对齐数排布的方式缓解了外碎片,但仍需注意内碎片问题。当前实现主要包含两个核心功能:内存申请与释放。
- 申请流程:请求 ≤256KB 内存时,先查找本地 ThreadCache 对应的自由链表。若链表非空,直接弹出对象;若为空,则向 CentralCache 批量获取对象填充链表后再使用。
- 释放流程:释放 <256KB 内存时,根据大小计算链表索引,将对象推回
_freeLists[i]。若链表过长,则将多余对象回收至 CentralCache。
2. 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;
}
bool empty {
_freelist == ;
}
:
* _freelist = ;
};


