垃圾回收 -- 标记压缩算法

标记- 压缩算法分为标记阶段和压缩阶段

压缩阶段通过数次搜索堆来重新装填活动对象, 压缩阶段并不会改变对象的排列顺序,只是缩小了它们之间的空隙,把它们聚集到了堆的一端

需要扫描三次

  1. 扫描整个堆, 设定forwarding 指针, 即是记录活动对象信息 事先将各对象的指针全部更新到预计
    要移动到的地址
  2. 更新指针 重写所有活动对象的指针
  3. 移动对象 将活动对象移动到forwarding 指针的引用目标处

特点:

可有效利用堆, 利用率高, 不用像复制算法需要预留空闲堆

压缩花费计算成本, 压缩算法需要搜索3次, 如果堆很大,那么,消耗的成本也会越来越大

Two-Finger 算法

需要搜索堆两次

必须将所有对象整理成大小一致

步骤:

  1. 移动对象
  2. 更新指针

是通过执行压缩操作来让活动对象填补空闲空间。此时为了让对象能恰好填补空闲空间,
必须让所有对象大小一致

利用放置非活动对象的空间来作为活动对象的目标空间,这是为了让移动前的对象不会在GC 过程中被覆盖掉。这样一来,我们就能把forwarding 指针设定在这个移动前的对象的域中,没有必要多准备出1 个字进行单独存储

更新指针, 指向移动后的对象

特点:

不需要额外的内存空间以用于forwarding 指针, 多浪费一个字的标志位, 二是只进行两次搜索

由于是将活动对象移动到非活动对象的空间, 对象的顺序在压缩前后产生了巨大的变化, 因此,对象的位置无法控制,也就无法进行缓存加速

表格算法

执行两次压缩操作

步骤:

  1. 移动对象(群)以及构筑间隙表格(break table)
  2. 更新指针

连续的活动对象群一并移动, 表格算法中则使用间隙表格来预留更新指针所用的信息

例如:

[ (950, 400), [200, 200], [500, 300]]

垃圾回收 -- 标记压缩算法_第1张图片

(950, 400) 说明起始地址是950, 大小是400个单位的大小

每次移动对象群时,都需要把移动前的信息注册到间隙表格里。注册入口是所移动的对象群的首地址(live)和此前对象群滑动大小(size)的组合。再移动的时候需要计算移动空间的大小

移动完成后更新指针, 引用移动前的对象的指针全部换成引用移动后的对象的指针

特点:

不要额外的空间进行交换

要维持间隙表格需要付出很高的代价。考虑到每次移动活动对象群都要进行表格的移动和更新。

在更新指针前,如果先将表格排序,则表格的搜索就能高速化, 但是排序也需要消耗时间

ImmixGC算法

immix 混合, 它将GC 标记- 清除算法和压缩组合在了一起

ImmixGC 把堆分为一定大小的“块”(block),再把每个块分成一定大小的“线”(line)。
这个算法不是以对象为单位,而是以线为单位回收垃圾的。
分配时程序首先寻找空的线,然后安排对象。没找到空的线时就执行GC

步骤:

  1. 选定备用的From 块
  2. 搜索阶段
  3. 清除阶段

不过该算法不是每次都执行步骤1 的。在ImmixGC 中,只有在堆消耗严重的情况下,
为了分配足够大小的分块时才会执行压缩。此时会通过步骤1 来选择作为压缩对象的备用块
(备用的From 块)。
接下来,在步骤2 中从根搜索对象,根据对象存在于何种块里来分别进行标记操作或复
制操作。具体来说,就是对存在于步骤1 中选择的备用From 块里的对象执行复制操作,对
除此之外的对象进行标记操作。
步骤3 则是寻找没有被标记的线,按线回收非活动对象

你可能感兴趣的:(计算机基础,gc,垃圾回收,标记压缩)