
💡Yupureki:个人主页
✨个人专栏:《C++》 《算法》《Linux系统编程》《高并发内存池》
🌸Yupureki🌸的简介:

目录
[1. 大块内存的申请](#1. 大块内存的申请)
[2. 大块内存的释放](#2. 大块内存的释放)
完整项目链接
https://github.com/Yupureki-code/ConcurrentMemoryPool
1. 大块内存的申请
ThreadCache和CentralCache内部能够存储的最大内存块为256kb。如果进程申请了超过256kb的内存块时,应该越级直接向PageCache申请
这个判断应该在最开始的向ThreadCache申请资源环节进行
cpp
static void* ConcurrentAlloc(size_t size)
{
if (size > MAX_BYTES)//大于256kb
{
size_t alignSize = SizeClass::RoundUp(size);
size_t kpage = alignSize >> PAGE_SHIFT;
PageCache::GetInstance()->_pageMtx.lock();
Span* span = PageCache::GetInstance()->NewSpan(kpage);//直接向PageCache申请
span->_objSize = size;
PageCache::GetInstance()->_pageMtx.unlock();
void* ptr = (void*)(span->_pageId << PAGE_SHIFT);
return ptr;
}
else
{
// 通过TLS 每个线程无锁的获取自己的专属的ThreadCache对象
if (pTLSThreadCache == nullptr)
{
static ObjectPool<ThreadCache> tcPool;
//pTLSThreadCache = new ThreadCache;
pTLSThreadCache = tcPool.New();
}
//cout << std::this_thread::get_id() << ":" << pTLSThreadCache << endl;
return pTLSThreadCache->Allocate(size);
}
}
同时PageCache内部能够存储的最大页数为128,因此有两种情况
- 内存块大于256kb 小于 128 * 8 kb,则可以在PageCache内部拿
- 如果大于128 * 8 kb,那么说明PageCache也做不到,应该越级向系统申请
因此当PageCache收到这个请求后,也应该做特殊对待
cpp
// 获取一个K页的span
Span* PageCache::NewSpan(size_t k)
{
assert(k > 0);
// 大于128 page的直接向堆申请
if (k > NPAGES-1)
{
void* ptr = SystemAlloc(k);
//Span* span = new Span;
Span* span = _spanPool.New();
span->_pageId = (PAGE_ID)ptr >> PAGE_SHIFT;
span->_n = k;
_idSpanMap[span->_pageId] = span;
return span;
}
.......
}
2. 大块内存的释放
当进程释放这个大块内存后,原来是向PageCache申请的,现在也应该直接向PageCache释放
cpp
static void ConcurrentFree(void* ptr)
{
Span* span = PageCache::GetInstance()->MapObjectToSpan(ptr);
size_t size = span->_objSize;
if (size > MAX_BYTES)//释放大块内存
{
PageCache::GetInstance()->_pageMtx.lock();
PageCache::GetInstance()->ReleaseSpanToPageCache(span);
PageCache::GetInstance()->_pageMtx.unlock();
}
else
{
assert(pTLSThreadCache);
pTLSThreadCache->Deallocate(ptr, size);
}
}
同时PageCache最大只能存储128页的内存块,因此如果大于128 * 8 kb的大小,应该直接向系统释放
cpp
void PageCache::ReleaseSpanToPageCache(Span* span)
{
// 大于128 page的直接还给堆
if (span->_n > NPAGES-1)
{
void* ptr = (void*)(span->_pageId << PAGE_SHIFT);
SystemFree(ptr);
//delete span;
_spanPool.Delete(span);
return;
}
......
}