1.申请内存
- 当Central Cache向Page Cache申请内存时,Page Cache先检查对应位置有没有span,如果没有则向更大页寻找一个span,如果找到则分裂成两个
- 比如:申请的是4页page,4页page后面没有挂span,则向后面寻找更大的span,假设在10页page位置找到一个span,则将10页page span分裂为一个4页page span和一个6页page span
- 如果找到_spanList[128]都没有合适的span,则向系统使用mmap、brk或者是VirtualAlloc等方式申请128页page span挂在自由链表中,再重复1中的过程
- 需要注意的是Central Cache和Page Cache的核心结构都是spanlist的哈希桶,但是他们是有本质区别的
- Central Cache中哈希桶,是按跟Thread Cache一样的大小对齐关系映射的,它的spanlist中挂的span中的内存都被按映射关系切好链接成小块内存的自由链表
- Page Cache中的spanlist则是按下标桶号映射的,也就是说第i号桶中挂的span都是i页内存
2.释放内存
- 如果Central Cache释放回一个span,则依次寻找span的前后page id的没有在使用的空闲span, 看是否可以合并,如果合并继续向前寻找。这样就可以将切小的内存合并收缩成大的span,减少内存碎片
3.框架
class PageCache
{
public:
static PageCache *GetInstance()
{
return &_sInit;
}
Span *NewSpan(size_t k);
Span *MapObjToSpan(void *obj);
void ReleaseSpanToPageCache(Span *span);
private:
PageCache()
{}
PageCache(const PageCache &) = delete;
private:
SpanList _spanList[NPAGES];
ObjectPool<Span> _spanPool;
PageMAP _idSpanMap;
static PageCache _sInit;
public:
std::mutex _pageMtx;
};