高并发内存池 - thread cache 回收内存

📅 2026/7/13 5:57:21
高并发内存池 - thread cache 回收内存
高并发内存池 - thread cache 回收内存在将申请内存的逻辑走通后我们进入到回收内存部分的实现首先从 Thread Cache 层开始。Thread Cache 层负责回收的函数是 Deallocate() 接下来讲解它的实现思路。外部在调用回收函数时需要传入空间的指针 ptr 与空间的字节大小 size我们要根据吃 size 的大小确定要归还到哪个自由链表中。所以现阶段可以将函数实现成如下逻辑voidThreadCache::Deallocate(void*ptr,size_t size)//归还空间{assert(ptr);//归还的空间不能为空指针assert(sizeMAX_BYTES);//归还空间的大小不能超过 MAX_BYTESsize_t indexSizeClass::Index(size);_freeList[index].Push(ptr);}Push 函数的实现如下在 Comm.h 中自由链表处添加实现voidPush(void*ptr){ObjNext(ptr)_freelist;_freelistptr;_size;//这个 size 前文并未提及下面会解释}但是 Thread Cache 层中不可能一直占据着空间资源如果自由链表上的空间过多应该将它归还到 Central Cache 层中那么如何定义归还的条件呢TCMalloc 中有许多实现条件我们只取其中较为核心的一条当自由链表上的空间数大于 MaxSize() 也就是一次申请的最大数量时我们将多出的空间归还。我们将空间归还函数命名为 ListTooLong()将自由链表 list 与空间字节大小 size 传入此时代码可以实现为voidThreadCache::Deallocate(void*ptr,size_t size)//归还空间{assert(ptr);//归还的空间不能为空指针assert(sizeMAX_BYTES);//归还空间的大小不能超过 MAX_BYTESsize_t indexSizeClass::Index(index);_freeList[index].Push(ptr);if(_freeList[index].Size()_freeList[index].MaxSize())//如果自由链表的长度大于了一次批量申请的数量{ListTooLong(_freeList[index],size);}}这里的 Size() 暂未在自由链表中实现并且关于空间资源数量的统计我们之前也并未实习所以现在完善 FreeList 类中的逻辑。//用于管理一个变量大小的自由链表classFreeList{public:voidPush(void*ptr){ObjNext(ptr)_freelist;_freelistptr;_size;}voidPushRange(void*start,void*end,size_t num){ObjNext(end)_freelist;_freeliststart;_sizenum;}void*Pop(){void*obj_freelist;_freelistObjNext(_freelist);returnobj;_size--;}boolEmpty(){return_freelistnullptr;}size_tMaxSize(){return_maxSzie;}size_tSize(){return_size;}private:void*_freelistnullptr;size_t _maxSzie1;size_t _size0;};将其完善后便可以思考 ListTooLong() 中的逻辑如何实现要将多余的空间资源取出然后将其交给 Central Cache 层那么在 Thread Cache 这一层所能做的就已经结束了。我们将 Central Cache 中归还内存的函数命名为 RealeaseListToSpan()voidRealeaseListToSpan(void*start,size_t byte_size);代码实现voidThreadCache::ListTooLong(FreeListlist,size_t size){void*startnullptr;void*endnullptr;list.PopRange(start,end,list.MaxSize());CentralCache::GetInstance()-RealeaseListToSpan(start,size);}再将上面的代码实现看完后有一点需要讲解这里为什么不用将 end 也传入呢因为 end 指向的下一个空间为 nullptr所以在函数中直接判断即可PopRange 的实现如下在 Comm.h 的 FreeList 中实现voidPopRange(void*start,void*end,size_t n){assert(_sizen);start_freelist;endstart;for(inti0;in-1;i)//因为 start 本身就是一块空间所以再取 size - 1 次即可{endObjNext(end);}_freelistObjNext(end);ObjNext(end)nullptr;_size-n;}到此 Thread Cache 层中内存回收目前阶段所能实现的代码就这么多在下篇文章我们进入 Central Cache 层中进行实现。