优势
- 内存碎片问题。(尽量缓解)
- 性能问题。(提高申请内存的效率)
- 多核多线程环境下,锁竞争问题
结构
threadCache
class ThreadCache
{
public:void* Allocate(size_t size);void Deallocate(void* ptr,size_t size);void* FetchFromCentralCache(size_t index, size_t size);void ListTooLong(FreeList* list, size_t size);private:FreeList _freelist[NLISTS];
};
_declspec (thread) static ThreadCache* tlslist = nullptr;
TLS技术:使每个线程都有一个tlslist
主要功能:
申请内存,有内存时直接从链表中拿取,没有的话从CentralCache中申请
释放内存:当在一个链表的后面挂的内存达到一定数量的时候,就归还给CentralCache
CentralCache
class CentralCache
{
public:static CentralCache* GetInstance(){return &_inst;}//从Page Cache获取一个SpanSpan* GetOneSpan(SpanList& spanlist, size_t byte_sizes);//从中心缓存获取一定数量的对象给Thread Cachesize_t FetchRangeObj(void*&start, void*&end, size_t n, size_t byte_sizes);//将一定数量的对象释放到span跨度void ReleaseListToSpan(void* start, size_t size);
private:SpanList _spanlist[NLISTS];
private:CentralCache(){}CentralCache(CentralCache&) = delete;static CentralCache _inst;
};
实现功能:
获取内存:当threadCache向CentralCache申请内存时,如果对应的链表上有内存的话,根据计算取出给threadCache,倘若没有,找PageCache申请
合并内存:当对应的span全部被释放的时候,就会进行合并算法,合成一块大内存,还给PageCache
PageCache
class PageCache
{
public:static PageCache* GetInstance(){return &_inst;}Span* NewSpan(size_t size);Span* MapObjectToSpan(void* obj);void ReleaseSpanToPageCache(Span* span);private:SpanList _spanlist[NPAGES];std::map<PageID, Span*> _idspanmap;
private:PageCache(){}PageCache(const PageCache&) = delete;static PageCache _inst;};
功能:
申请内存:直接在共享区划分一部分内存,申请128页的,挂在对应的链表上
合并内存:合并对应的span,小的往大合并
性能
- 加锁区间小,只有在对应的CentralCache的对应大小的链表上申请内存时,才需要加锁
- 减少了内存碎片,控制在12%左右
- 一次申请批量,提高了效率