zoukankan      html  css  js  c++  java
  • 《垃圾回收的算法与实现》——GC标记-压缩算法

    基本算法

    • Mark-Compact与Mark-Sweep的第一阶段均为标记活跃对象,第二阶段则不同,压缩算法则是将活跃对象逻辑上移到一起。

    Lisp2算法

    • 对象头中增加forwarding指针,其用法与复制算法一样。
    • Lisp2的标记阶段与其他算法一样,其压缩算法则包括以下三个步骤:
      • 设定forwarding指针,遍历堆根据标记的活跃对象计算出每个对象的forwarding并给其设置进去。
      • 更新指针,遍历GC root将其引用修改为对应对象的forwarding,重新遍历堆将引用更新为对象的forwarding。
      • 移动对象,将活动对象移动到第一步计算的forwarding的位置,移动后将forwarding设为null。

    优缺点

    优点

    1. 相对复制算法提高堆的利用率。
    2. 相对清除算法不会产生碎片。

    缺点

    1. Lisp2中的压缩阶段需要遍历3次堆。

    改进

    Two-Finger算法

    减少遍历次数

    • 限制条件为必须将对象整理为大小一致
    • 对象中不需要专门设forwarding字段,直接使用对象的第一个字段当forwarding。
    • 其压缩步骤如下:
      • 移动对象,free指针指向堆头,live指针指向堆尾。free寻找垃圾对象,live指针寻找有效对象,而后将堆尾的有效对象复制到堆头的垃圾对象上。同时在被复制堆尾对象上设置forwarding。
      • 更新指针,遍历复制结束的堆,如果引用大于free则需要更新其引用为forwarding。
    • 优点压缩步骤只需要遍历两次堆,且不需要给对象增加forwarding字段。
    • 缺点无序的复制不一定能兼容缓存,且需要对象一样大这个很难办到(BiBOP可以使用)。

    表格算法

    减少遍历次数

    • 原理通过间隙表格记录对象需要移动的距离以推断其引用的改变结果。
    • 将连续的活跃对象向堆头移动,每个连续的对象群记录一个位置和移动距离。
    • 具体步骤如下:
      • 移动对象群,从堆头开始搜索连续的活跃对象,将其第一个对象的位置和需要移动的距离写入间隙表格中(间隙表格的移动有点晕我也觉得没必要那么复杂的移动,直接写到一个固定的位置就好)
      • 更新指针,遍历GC root和堆中对象,找出其引用的对象位置属于那个间隙表格的记录,而后将其引用减去对应的距离。
    • 优点减少了压缩的遍历次数且保留了活跃对象的相对位置。
    • 缺点维护间隙表格需要比较大的代价,其次间隙表格的记录如果是乱序的话每个对象的搜索会变成一个O(N)的复杂度。

    Immix GC算法

    1. 堆的构成

    • 堆分成一定大小(32KB)的块(block),而后再把block分成一定大小(128B)的线(line),其以line为回收单位。
    • block中有以下域:
      • line:数组,表示block中的线
      • mark_table:数组,表示对应线的标记。FREE(线中没对象)、MARKED(标记已完成)、ALLOCATED(有对象)、CONSERVATIVE(保守标记)
      • status:表示整个block的状态,FREE(页为空)、RECYCLABLE(一部分线为空)、UNAVAILABLE(没有空的线)
      • hole_cnt:block中连续的大于等于1个的空line的个数
    • Immix GC根据对象大小进行分类,小型对象:比线小的;中型对象:不到8KB;大型对象:大于等于8KB。Immix GC不管理大型对象

    2. 分配

    • 使用cursor和limit两个指针指向RECYCLABLE block的孔的开头和结尾来采用复制算法的分配方法,当该孔空间不够时则找下一个孔。
    • 通过两个指针向右移动寻找剩下的孔,如果该block无孔了则将status置为UNAVAILABLE而后从其他RECYCLABLE中寻找孔。
    • 当不能在cursor和limit之间分配中型对象时,则直接在FREE block中分配线。
    • 线中分配了对象后其对应的mark_table将置为ALLOCATED
    • 当小型对象占用了多个线时,后续的线状态置为CONSERVATIVE。

    3. 步骤

    • 选定备用From块,该步需要满足一定条件才会执行,根据孔数作为碎片化测量的指标来选择From块。
    • 搜索阶段,递归遍历GC root其引用的对象所在的线标记为Marked,From块中的对象复制到To块中。复制到To块不一定钥匙FREE block也可以是一个大孔。
    • 清除阶段,以线为单位进行清除,mark_table标记为ALLOCATED的线直接置为FREE,MARKED的置为ALLOCATED,CONSERVATIVE的则根据前一个线的状态决定,前个线为ALLOCATED则不需要改变,为FREE则也置为FREE

    4. 总结

    • 优点:将堆变为block和line的管理,解决了碎片化的问题。
    • 缺点:对象不是按顺序保存,缓存不兼容
  • 相关阅读:
    限定类型后undefined变null
    学习进度条(第一周)
    记账本开发小计(三)
    记账本开发小计(四)
    记账本开发小计(五)
    个人作业1数组
    记账本开发小计(二)
    记账本开发小计(七)
    记账本开发小计(六)
    软件工程概论第一次课堂测试(实发项目的开发)总结
  • 原文地址:https://www.cnblogs.com/suolu/p/6657990.html
Copyright © 2011-2022 走看看