1 Star 0 Fork 0

Fan_558/HighlyConcurrentMemoryPools

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
PageCache.cpp 5.20 KB
一键复制 编辑 原始数据 按行查看 历史
Fan_558 提交于 1年前 . HighlyConcurrentMemoryPools
#include "PageCache.h"
PageCache PageCache::_sInst;
// 获取一个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;
//_threadMtx.lock();
Span* span = _spanPool.New();
//_threadMtx.unlock();
span->_pageId = (PAGE_ID)ptr >> PAGE_SHIFT;
span->_n = k;
//_idSpanMap[span->_pageId] = span; //建立映射关系
_idSpanMap.set(span->_pageId, span);
return span;
}
//检查pagecache第K个桶是否有span
if (!_spanLists[k].Empty())
{
Span* kSpan = _spanLists[k].PopFront();
// 建立id和span的映射,方便central cache回收小块内存时,查找对应的span
for (PAGE_ID i = 0; i < kSpan->_n; ++i)
{
//_idSpanMap[kSpan->_pageId + i] = kSpan;
_idSpanMap.set(kSpan->_pageId + i, kSpan);
}
return kSpan;
}
//查看第K个桶的后面的桶是否有span(K+1:跳过当前没有span的桶)
for (size_t i = k + 1; i < NPAGES; ++i)
{
if (!_spanLists[i].Empty())
{
//切分span
Span* nSpan = _spanLists[i].PopFront();
//Span* kSpan = new Span;
//_threadMtx.lock();
Span* kSpan = _spanPool.New();
//_threadMtx.unlock();
// 在nSpan的头部切一个k页下来
// k页span返回
// nSpan再挂到对应映射的位置
kSpan->_pageId = nSpan->_pageId;
kSpan->_n = k;
nSpan->_pageId += k;
nSpan->_n -= k;
//将切分剩下的页缓存重新挂起来
_spanLists[nSpan->_n].PushFront(nSpan);
//存储Nspan的首位页号与Nspan映射,方便page cache回收内存时进行合并查找
//_idSpanMap[nSpan->_pageId] = nSpan;//首
//_idSpanMap[nSpan->_pageId + nSpan->_n - 1] = nSpan;//尾
_idSpanMap.set(nSpan->_pageId, nSpan);//首
_idSpanMap.set(nSpan->_pageId + nSpan->_n - 1, nSpan);//尾
// 建立id和span的映射,方便central cache回收小块内存时,查找对应的span
for (PAGE_ID i = 0; i < kSpan->_n; ++i)
{
//_idSpanMap[kSpan->_pageId + i] = kSpan;
_idSpanMap.set(kSpan->_pageId + i, kSpan);
}
return kSpan;
}
}
//其余桶为空,此时向(堆)系统申请一个128Page的内存块
//Span* bigSpan = new Span;
//_threadMtx.lock();
Span* bigSpan = _spanPool.New();
//_threadMtx.unlock();
void* ptr = SystemAlloc(NPAGES - 1);
bigSpan->_pageId = (PAGE_ID)ptr >> PAGE_SHIFT;
bigSpan->_n = NPAGES - 1;
//在pagecache对应的桶中插入刚申请的内存span
_spanLists[bigSpan->_n].PushFront(bigSpan);
//复用自己,重新进行切分
return NewSpan(k);
}
Span* PageCache::MapObjectToSpan(void* obj)
{
PAGE_ID id = ((PAGE_ID)obj >> PAGE_SHIFT);
//std::unique_lock<std::mutex> lock(PageCache::_pageMutex); //构造时加锁,析构时自动解锁
//auto ret = _idSpanMap.find(id);
//if (ret != _idSpanMap.end())
//{
// return ret->second;
//}
//else
//{
// assert(false);
// return nullptr;
//}
Span* ret = (Span*)_idSpanMap.get(id);
//if (ret == nullptr)
//{
// int x = 0;
//}
assert(ret != nullptr);
return ret;
}
void PageCache::ReleaseSpanToPageCache(Span* span)
{
// 大于128 page的直接还给堆
if (span->_n > NPAGES - 1)
{
void* ptr = (void*)(span->_pageId << PAGE_SHIFT);
SystemFree(ptr);
//delete span;
//_threadMtx.lock();
_spanPool.Delete(span);
//_threadMtx.unlock();
return;
}
//// 对span前后的页,尝试进行合并,缓解内存碎片问题
//while (1)
//{
// PAGE_ID prevId = span->_pageId - 1;
// auto ret = _idSpanMap.find(prevId);
// //查找前一个span是否存在,若查找到尾,则不存在
// if (ret == _idSpanMap.end())
// {
// break;
// }
// // 前面相邻页的span在使用,不合并了
// Span* prevSpan = ret->second;
// if (prevSpan->_isUse == true)
// {
// break;
// }
// // 合并出超过128页的span没办法管理,不合并了
// if (prevSpan->_n + span->_n > NPAGES - 1)
// {
// break;
// }
// //合并前后页
// span->_pageId = prevSpan->_pageId;
// span->_n += prevSpan->_n;
// //将以被合并的span从链表中解除
// _spanLists[prevSpan->_n].Erase(prevSpan);
// //delete prevSpan;
// _threadMtx.lock();
// _spanPool.Delete(prevSpan);
// _threadMtx.unlock();
//}
// 对span前后的页,尝试进行合并,缓解内存碎片问题
while (1)
{
PAGE_ID prevId = span->_pageId - 1;
Span* ret = (Span*)_idSpanMap.get(prevId);
//查找前一个span是否存在,若查找到尾,则不存在
if (ret == nullptr)
{
break;
}
// 前面相邻页的span在使用,不合并了
Span* prevSpan = ret;
if (prevSpan->_isUse == true)
{
break;
}
// 合并出超过128页的span没办法管理,不合并了
if (prevSpan->_n + span->_n > NPAGES - 1)
{
break;
}
//合并前后页
span->_pageId = prevSpan->_pageId;
span->_n += prevSpan->_n;
//将以被合并的span从链表中解除
_spanLists[prevSpan->_n].Erase(prevSpan);
//delete prevSpan;
//_threadMtx.lock();
_spanPool.Delete(prevSpan);
//_threadMtx.unlock();
}
// 向后合并
while (1)
{
PAGE_ID nextId = span->_pageId + span->_n;
Span* ret = (Span*)_idSpanMap.get(nextId);
//查找前一个span是否存在,若查找到尾,则不存在
if (ret == nullptr)
{
break;
}
Span* nextSpan = ret;
if (nextSpan->_isUse == true)
{
break;
}
if (nextSpan->_n + span->_n > NPAGES - 1)
{
break;
}
span->_n += nextSpan->_n;
_spanLists[nextSpan->_n].Erase(nextSpan);
//delete nextSpan;
//_threadMtx.lock();
_spanPool.Delete(nextSpan);
//_threadMtx.unlock();
}
//插入所合并好的span
_spanLists[span->_n].PushFront(span);
span->_isUse = false;
_idSpanMap.set(span->_pageId, span);
_idSpanMap.set(span->_pageId + span->_n - 1, span);
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/Fan_558/highly-concurrent-memory-pools.git
git@gitee.com:Fan_558/highly-concurrent-memory-pools.git
Fan_558
highly-concurrent-memory-pools
HighlyConcurrentMemoryPools
master

搜索帮助