如何实现内存页的分配与释放

内存革命

一、再梳理一下内存结构
1、内存memmgrob_t被划分为多个功能分区,每个功能分区用一个memarea_t描述
2、每个memarea_t都有一个memdivmer_t ,每个memdivmer_t 都有一个bafhlst_t数组[0-51]
3、每个bafhlst_t都有一个链表,用于存放内存段,规则为:
bafhlst_t数组中的每个bafhlst_t,会根据其在数组中的序号n,存放全部2的n次方的连续页面,也就是说:
第0个bafhlst_t,存放全部长度为1的内存段
第1个bafhlst_t,存放全部长度为2的内存段
第2个bafhlst_t,存放全部长度为4的内存段
……
4、在内存段处理时,将开始的msadsc_t指向了最后msadsc_t结构,内存段的起止就都清晰了,而且无论首尾,都记录了分配情况,方便各类操作
5、所以从设计层面来讲,页面的分配和释放,也一定只会是2的n次方大小

二、申请
1、根据类型找到内存区,也就是定位到了memarea_t->memdivmer_t->bafhlst_t数组
2、根据申请内存大小,用二进制1的查找,确定要至少要从bafhlst_t数组中的哪个bafhlst_t申请,才能得到足够大的内存
3、从第一个合适的bafhlst_t到最大的bafhlst_t,依次判断链表中有没有可用内存段,一旦有可用的内存段就使用
4、如果内存段大于所需,就要把多出来的内存不断除以2挂载到上一个bafhlst_t,直到达到所需长度
5、设置内存段状态,起始msadsc_t都标记为已占用
6、更新各层结构相关信息,内存申请结束
7、代码中还有各种加锁解锁,各种校验,还有从大到小申请的一种方式,可以看下

三、释放
1、根据要释放内存段的msadsc_t,获取属于哪个内存区,也就是定位到了memarea_t->memdivmer_t->bafhlst_t数组
2、根据释放内存大小,用二进制1的查找,确定最大可以释放到bafhlst_t数组中的哪个bafhlst_t,避免内存碎片化
3、设置内存段状态,起始msadsc_t都标记为未使用
4、从找到的第一个bafhlst_t到最大的bafhlst_t,依次去看链表中有没有内存段是挨着的,如果有就合并,再去下一个bafhlst_t继续合并
一旦某个bafhlst_t中没能合并,就可以退出了,因为我们只存2的n次方大小的内存段
而且每次合并内存段后,都要清理多余的标记,而且开始的msadsc_t要指向最后的msadsc_t
5、把最终合并后的内存段,加入到对应的bafhlst_t中,重新设置内存段的起始msadsc_t标记
6、更新好各层结构相关信息,内存释放结束
7、代码中还有各种加锁解锁,各种校验,可以看下

四、对于最后的问题
其实无论采用哪种分配方式,内存的碎片化都是难以彻底避免的。无论是操作系统、虚拟机还是应用,都要面对这个问题。业界有多种思路来解决或缓解此问题:
1、把不可移动内存单独管理,系统内存分区其实在一定程度上解决了这些问题
2、linux采用了 buddy system来缓解内存碎片问题,本节已经介绍
3、linux中为了处理特别小的内存请求,引入了slab技术,来辅助buddy system
4、windows有一种LFH技术,在程序启动时,会额外分配一定的连续内存给这个进程备用,从而降低系统层面的内存管理负担
5、windows在进程退出后,不会立即释放dll文件相关内存,一方面提速,一方面也缓解了操作系统内存管理负担。其实,看下你手机的APP,切换到后台时,就是这个效果
6、无论是linux还是windows都有低优先级进程,在后台默默做着内存规整工作,类似于磁盘碎片清理
7、JVM虚拟机,GC时会通过标记-整理(比如CMS)或复制-清除(比如G1)的方法来解决部分碎片问题
8、类似与LFH,可以考虑在内存分配时额外预留一部分,下次分配在预留的地方继续分配
9、为了内存规整方便,可以考虑靠近应用已分配内存区域进行分配
10、还有一种思路,就是将不连续的内存,转换为逻辑上连续的内存,来绕过碎片化问题,但一些情况下性能难以保证

应用层面也有工作能做:
1、比如redis在处理内存的时候,申请时会额外申请一部分先备着【记得是jemalloc】,释放时也不会立即释放,有单独的线程进行处理,在应用层面去降低系统内存管理负担
2、同时,redis在数据结构上也做了很多努力
3、在写程序的时候,尽量不要零零散散的去申请大量小内存;
4、除了标准库以外,可以试一下 jemalloc或Doug Lea’s malloc
5、感兴趣可以看下redis内存管理的代码
额,好像跑题了。。。

Xuanwei Zhang
Xuanwei Zhang
Software Engineer

My research interests include distributed database, distributed storage system and internet of things