05 空间的回收

文章详细阐述了一个内存管理系统中的三层资源回收流程,包括ThreadCache层的直接返还,CentreCache层的Span块回收,以及PageCache层的复杂合并操作,旨在减少内存碎片并优化内存使用。在PageCache层,通过合并相邻的空闲页来创建更大的Span包,以适应不同大小的内存请求,同时避免无效的内存浪费。
摘要由CSDN通过智能技术生成

        当用户将从线程资源层申请的内存块返还给线程资源层后,一系列复杂的回收工程就开始了。

一、ThreadCache层的回收

        当用户调用内存块释放接口时,直接将内存块插入回线程资源层的对应桶里即可。

二、CentreCache层的回收

        当ThreadCache层的回收工作的结尾处,做一个检测,当检测到回收了内存块的ThreadCache的桶里的内存块数量达到一定值时(可以是MaxSize的值和其它更精细的方案,如检测整个ThreadCache层的资源是否超标),就调用中心资源层的接口,将桶里的全部内存块回收到中心资源层对应桶里的Span块内。

         

 

         注意,每个内存块都可能属于不同的Span包,那么怎么找到内存块原本属于的Span包是哪个呢?(必须归还回原本属于的Span包,这样才能进一步归还回页缓存资源层)

        中心资源层的Span包来自于页缓存资源层,它们内存放的是一页一页的内存,实际上可以在页缓存资源层将Span包分配给中心资源层时,就将Span包内的每一页的页号与Span包对应起来(包括被分割后插入回PageCache的Span包)。那么只需要由内存块的地址计算出页号,再根据页号查找出其所属的Span包即可了。

可以借助unordered_map(哈希map)来完成这个页号与所属Span块的对照表:

std::unordered_map<PAGE_ID, Span*> Page_Span;

三、PageCache层的回收

        PageCache层的回收要复杂一些,因为它还要负责完成Span包的合并。在01.整体框架设计​​​​​​

中有过介绍:

         其中所谓的“会将相邻的空闲页进行合并”其实就是Span包的合并。

        通过上一节04 页缓存资源层的初步设计的介绍可知,PageCache每次都只会向系统申请一个多达128页的超大Span包,PageCache内的各个Span包都是由这个超大Span包分割而来的。那么问题来了,假使一个128页的Span包被分割成一个60页的Span包和68页的Span包,下次要申请一个100页的Span包了该怎么办呢?如果重新向系统申请一个128页的超大Span包就太浪费了。

        因此, 在CentreCache层的回收工作的结尾处也要做一个检测,即检测到某个Span包内的内存块已经全部回收后,就将整个Span包回收给PageCache。PageCache接收到Span包后,并不直接将之插入进对应的页桶里去,而是先试着与临近的左右页桶合并,试图合并成包含更多页的大Span包,直到不能再合并为止,最后才将该Span包插入回对应大小的页桶里去。

这是PageCache的逻辑结构:

        但实际上,在内存空间中,每个Span包都是紧挨着的,仅靠页号定义一个Span的头,含有的页数来定义一个Span的尾。 

 

         那么假设上图中占有第125页到135页的Span包从CentreCache层被归还,就可以一直向前合并到第120页,再向后合并到第149页,组成一个多达29页的Span包,并将之插入回29号页桶。

        Span包合并的过程其实相当简单,只需要根据本Span包的前一页或后一页的页号,从unordered_map<PAGE_ID, Span*> Page_Span中查找到该页所属的Span包,然后将本Span页的起始页号修改成新Span的页号,所含页数修改为新Span的页数,然后删除被合并的Span即可。

在以下三种情况下,Span包应立即停止合并:

  1. 前一个Span包或后一个Span包的is_used字段值为true,代表该Span包正在被上层使用,应停止本方向的合并。
  2. 没有从unordered_map<PAGE_ID, Span*> Page_Span中找到前一页或后一页所属的Span包。意味着,该页已经不在系统分配给本内存池的内存区域中,应停止本方向的合并。
  3. 如果进行合并,合并后的Span包大小将超过128页(两个超大128页原始Span正好完全挨着的情况),这超过了PageCache层管理的上限,应停止本方向的合并。

        通过三层资源的有序回收,有效地缓解了内存池中会出现内存碎片,导致小内存块太多,没有大内存块可用的问题。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值