高并发内存池(六)Page Cache回收功能的实现

当Page Cache接收了一个来自Central Cache的Span,根据Span的起始页的_pageId来对前一页所对应的Span进行查找,并判断该Span,是否处于使用状态,从而看是否可以合并,如果可以合并继续向前寻找。

当该Span前的空闲Span查找完毕后,就根据当前Span的_pageId+Span中的页数_n来向后查找后一页的Span是否为空闲状态,如果为空闲状态就继续向后合并。

这样就可以将切小的内存合并成大的Span,再次申请内存时,可以再从大Span中切分出小的,这样一来就大大减少了内存碎片,提高了空间的利用效率。

// 释放空闲span回到Pagecache,并合并相邻的span
void PageCache::ReleaseSpanToPageCache(Span* span)
{
	//将Central不用的Span进行回收
	//同时查找该Span的前后页是否属于空闲状态
	while (1)
	{
		PAGE_ID prevId = span->_pageId - 1;
		auto ret = _idSpanMap.find(prevId);
		if (ret == _idSpanMap.end())//没有找到说明没有该页号,直接break
		{
			break;
		}
		Span* prevspan = ret->second;
		if (prevspan->_isUse == true)//如果前面的页处于使用状态,直接break
		{
			break;
		}
		if (span->_n + prevspan->_n > 128)
		{
			break;
		}
		span->_pageId = prevspan->_pageId;
		span->_n += prevspan->_n;
		_spanList[prevspan->_n].Erase(prevspan);
		delete prevspan;
	}
	while (1)
	{
		PAGE_ID nextId = span->_pageId + span->_n;
		auto ret = _idSpanMap.find(nextId);
		if (ret == _idSpanMap.end())//没有找到说明没有该页号,直接break
		{
			break;
		}
		Span* nextspan = ret->second;
		if (nextspan->_isUse == true)//如果前面的页处于使用状态,直接break
		{
			break;
		}
		if (span->_n + nextspan->_n > 128)
		{
			break;
		}
		
		span->_n += nextspan->_n;
		_spanList[nextspan->_n].Erase(nextspan);
		delete nextspan;
	}
	if (span->_n == 128)
	{
		int x = 0;
	}
	_spanList[span->_n].PushFront(span);
	span->_isUse = false;
	_idSpanMap[span->_pageId] = span;
	_idSpanMap[span->_pageId + span->_n - 1] = span;
}

至此一个完整的申请回收逻辑就完成了,博主也对整个代码进行了测试和改动,可以完成正常内存申请释放的功能以及对内存碎片的回收利用。后面博主还会对代码进行进一步的优化和改进,从而对其中一些不足之处进行补充。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C+五条

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值