GC标记-清除算法(Mark Sweep GC)
Posted leisurelylicht
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GC标记-清除算法(Mark Sweep GC)相关的知识,希望对你有一定的参考价值。
- 世界上第一个GC算法,由 JohnMcCarthy 在1960年发布。
标记-清除算法由标记阶段和清除阶段构成。
标记阶段就是把所有的活动对象都做上标记的阶段。
- 标记阶段就是“遍历对象并标记”的处理过程。
- 标记阶段经常用到深度优先搜索。
清除阶段就是把那些没有标记的对象,也就是非活动对象回收的阶段。
- 清除阶段collector会遍历整个堆,回收没有打上标记的对象(即垃圾)。
- 内存的合并操作也是在清除阶段进行的。
分配
- 分配指将回收的内存空间进行再利用。
-> 伪代码实现内存分配 new_obj(size){ chunk = pickup_chunk(size, $free_list) if(chunk != NULL) return chunk else allocation_fail() //大招,销毁并释放全部空间 }
优点
- 实现简单
- 与保守式GC算法兼容
缺点
碎片化(fragmentation)
- 使用过程中会逐渐产生被细化的分块
分配速度
- 分块不连续,每次分配都必须遍历空闲链表,以便找到足够大的分块。
- 最糟的情况就是每次分配都要遍历全部空闲链表
与写时复制技术(copy-on-write)不兼容
为了解决分配速度的问题, 人们提出了两种方法
使用多个空闲链表(multiple free-list)
- 类似于建立索引的方法。
- 为了防止空闲链表(也就是索引)的数组过大的问题,通常会给分块大小设定一个上限。
大于这个上限的按照一个空闲链表处理。
- ex.
- 设置上限为100
- 那么准备1~100及大于等于101个字的100个空闲链表就可以了。
-> 伪代码实现使用多个空闲链表的内存分配 new_obj(size){ index = size / (WORD_LENGTH / BYTE_LENGTH) if(index <= 100) if($free_list[index] != NULL) chunk = $free_list[index] return chunk else chunk = pickup_chunk(size, $free_list[101]) if(chunk != NULL) return chunk allocation_fail() //大招,销毁并释放全部空间 }
BiBOP(Big Bag Of Pages)法
以上是关于GC标记-清除算法(Mark Sweep GC)的主要内容,如果未能解决你的问题,请参考以下文章