美文网首页
GC学习笔记(四)GC复制算法

GC学习笔记(四)GC复制算法

作者: 刘景昌 | 来源:发表于2020-07-06 15:48 被阅读0次

1.什么是复制算法

GC 复制算法是利用 From 空间进行分配的。当 From 空间被完全占满时,GC 会将活动
对象全部复制到 To 空间。当复制完成后,该算法会把 From 空间和 To 空间互换,GC 也就结
束了。From 空间和 To 空间大小必须一致。这是为了保证能把 From 空间中的所有活动对象
都收纳到 To 空间里。
复制算法执行过程图解


image.png
image.png
image.png
image.png

2.复制算法的优点

优秀的吞吐量

GC 标记 - 清除算法消耗的吞吐量是搜索活动对象(标记阶段)所花费的时间和搜索整体堆(清除阶段)所花费的时间之和。
另一方面,因为 GC 复制算法只搜索并复制活动对象,所以跟一般的 GC 标记 - 清除算法相比,它能在较短时间内完成 GC。也就是说,其吞吐量优秀。
尤其是堆越大,差距越明显。GC 标记 - 清除算法在清除阶段所花费的时间会不断增加,
但 GC 复制算法就不会产生这种消耗。毕竟它消耗的时间是与活动对象的数量成比例的。

可实现高速分配

GC 复制算法不使用空闲链表。这是因为分块是一个连续的内存空间。因此,调查这个
分块的大小,只要这个分块大小不小于所申请的大小,那么移动 $free 指针就可以进行分配了。

不会发生碎片化

活动对象被集中安排在 From 空间的开头对吧。像这
样把对象重新集中,放在堆的一端的行为就叫作压缩。在 GC 复制算法中,每次运行 GC 时
都会执行压缩。
因此 GC 复制算法有个非常优秀的特点,就是不会发生碎片化。也就是说,可以安排分块允许范围内大小的对象。

与缓存兼容

那就是 mutator 执行速度极快。近来很多 CPU 都通过缓存来高速读取位置较近的对象。这也是借助压缩来完成的,通过压缩来把有引用关系的对象安排在堆中较近的位置。

2.复制算法的缺点

堆使用效率低下

GC 复制算法把堆二等分,通常只能利用其中的一半来安排对象。也就是说,只有一半堆能被使用。相比其他能使用整个堆的 GC 算法而言,可以说这是 GC 复制算法的一个重大的缺陷。

递归调用函数

在这里介绍的算法中,复制某个对象时要递归复制它的子对象。因此在每次进行复制的时候都要调用函数,由此带来的额外负担不容忽视。大家都知道比起这种递归算法,迭代算法更能高速地执行

改进

使用迭代替递归
执行过程图解

image.png
首先复制所有从根直接引用的对象,在这里就是复制 B 和 G。
image.png
首先复制所有从根直接引用的对象,在这里就是复制 B 和 G。
image.png
搜索 BꞋ,然后把被 BꞋ 引用的 A 复制到了 To 空间,同时把 scan 和 free 一致,所以最后只要把 From 空间和 To 空间互换,GC 就结束了。
image.png
接下来按 B、G、A、E 的顺序来搜索对象。第一种GC 复制算法采用的是深度优先搜索,而 第二种的复制算法采用的则是广度优先搜索。
广度优先搜索是需要FIFO队列的,需要把对象一边保持在队列中一边进行搜索
实际上 scan 和 free 每次向右移动,队列里就会追加对象,scan 每次向右移动,都会有对象被取出和搜索。这样一来就满足了先入先出队列的条件,即把先追加的对象先取出。像这样把堆兼用作队列,这个算法的一大优点。不用特意为队列留出多余的内存空间就能进行搜索。
改进后优点

而 这个的 GC 复制算法是迭代算法,因此它可以抑制调用函数的额外负担和栈的消耗。特别是拿堆用作队列,省去了用于搜索的内存空间这一点,实在是令人赞叹。

改进后缺点

改进后具有引用关系的对象可能不再相邻,失去了充分利用缓存的优势

再次改进

使用广度优先遍历的得迭代代替了递归 ,但是同时也失去了引用对象相邻的优势,那么我们改如何同时保留两种优势呢?
下面为大家介绍下面我们将为大家介绍 Paul R. Wilson、Michael S. Lam 和 Thomas G. Moher 于 1991 年提出的近似深度优先搜索法。这个方法虽然只是近似深度优先搜索,不过这样一来就能通过深度优先搜索执行 GC 复制算法了。
首先我们先看一下按到第二种GC遍历是每个页面的内存分布情况
首先假设每个对象都是两个字节,每个页面大小为6个字节
第二种GC页面分布状况

image.png
在第 0 页中,A 和其引用的 B、C 已经配置好了,形成了理想的状态。不过,在其他的第 1 页至第 4 页中,同一页面里的对象间都没有引用关系。因此每次访问这些对象时,都要浪费时间去从内存上读取包含这些对象的页面。像这样,虽然程序能在广度优先搜索的一开始把对象安排在理想的状态,但随着搜索的推进,对象的安排就逐渐向着不理想的状态发展了。
在近似深度优先搜索法中有四个重要的变量
• page[i] 指向第 i个页面的开头。
• local_scan[i] 指向第i 个页面中下一个应该搜索的位置。
• free :指向分块开头的指针
执行过程
首先复制 A 到 To 空间,然后搜索 A,复制 B 和 C。它们都被复制到了第 0 页。
image.png
因为 A 已经搜索完了,所以 free 在此指向第 1 页的开头,也就是说,在下一复制中对象会被安排到新的页面。在这种情况下,程序会从 local_scan 开始搜索。此外,当对象被复制到新页面时,程序会根据这个页面的 major_scan 还指向第 0 页,所以还跟之前一样从 $local_scan[0] 开始搜索。也就是说,下面要搜索 B image.png
首先复制了被 B 引用的 D,在这里 D 被安排到了 local_scan 进行搜索。此时 local_scan[1] 开始搜索对象 D。通过对 D 的搜索,复制了 H 和 I。 image.png
在这里第 1 页已经满了, local_scan[1] 的搜索暂停,
程序开始通过 $local_scan[0] 进行搜索。也就是说,再次开始对 B 的搜索。 image.png

对 B 的搜索结束后,E 被复制到了第 2 页。因为程序还要往新页面上复制对象,所以
local_scan[0] 的搜索再次暂停,开始通过local_scan[2] 进行搜索。
因此,下一个要搜索的是 E。通过对 E 的搜索复制 J 和 K

image.png

通过对 J 和 K 的搜索,第 2 页被填满了, free 指向第 3 页的开头。因此我们回到major_
scan,再次通过 $local_scan[0] 进行搜索。
接下来的操作和上述步骤一样,这里就不再详细说明了。搜索完对象 C,复制完 A 到 O
的所有对象之后的状态如图 所示。

image.png

这样终于搜索完第 0 页了, major_scan 指向page[1]。虽然还有没搜索过的对象,
但这些对象都没有子对象,所以程序不对它们进行复制。
最终的执行结果 如图所示

image.png
很明显能够看出,跟 Cheney 的使用广度优先搜索的 GC 复制算法不同,在使用近似深
度优先搜索的情况下,不管在哪一个页面里,对象间都存在着引用关系。
这样就可以既使用迭代代替递归 又可以使用缓存机制了

相关文章

  • GC学习笔记(四)GC复制算法

    1.什么是复制算法 GC 复制算法是利用 From 空间进行分配的。当 From 空间被完全占满时,GC 会将活动...

  • chapter-4 GC算法与种类

    GC 算法与种类 ■ GC的概念■ GC算法• 引用计数法• 标记清除• 标记压缩• 复制算法■可触及性■ Sto...

  • Android GC 学习笔记

    阅读的文章:Android GC 原理探究 下面补充一些备注和笔记。 算法 复制算法 (Copying)图示: 标...

  • JVM GC

    GC 概念 GC分类 引用计数法 可到达分析 GC内存回收算法 复制 标记清理 标记整理 参考文章 咱们从头到尾说...

  • GC - 复制算法

    是什么 copy() new_obj() 执行 优点 吞吐量 可实现高速分配 不会碎片化 与缓存兼容 缺点 堆使用...

  • 面试官,不要再问我“Java 垃圾收集器”了

    如果Java虚拟机中标记清除算法、标记整理算法、复制算法、分代算法这些属于GC收集算法中的方法论,那么“GC收集器...

  • 面试官,不要再问我“Java 垃圾收集器”了

    如果Java虚拟机中标记清除算法、标记整理算法、复制算法、分代算法这些属于GC收集算法中的方法论,那么“GC收集器...

  • GC算法

    GC的算法 1、复制 2、标记-清理 3、标记-整理

  • GC评价标准

    吞吐量 gc的吞吐量为 HEAP_SIZE/GC_COST_TIMEGC复制算法和标记清楚算法相比,活动对象越少,...

  • GC垃圾回收机制

    GC算法 垃圾收集器 (标记-清除,复制,压缩,gc垃圾收集需要判断是否覆盖finalize方法?) 概述 垃圾收...

网友评论

      本文标题:GC学习笔记(四)GC复制算法

      本文链接:https://www.haomeiwen.com/subject/ohffqktx.html