9阅网

您现在的位置是:首页 > 知识 > 正文

知识

java - G1算法中的记忆集是用来干什么的?

admin2022-11-05知识17

我刚刚看了一些关于G1算法的博客。

我对 remembered-set 的用法感到很困惑。

我是这么认为的。

既然我们可以用DFS来遍历GC -Roots中的每一个引用 那为什么我们还需要remembered -set?

因为所有的博客都说,我们之所以使用remembered-set,是因为我们不需要检查每一个区域,看看是否有一个对象被GC-Roots引用了。



【回答】:

你需要了解什么是 Card Table 是第一的,IMO。你如何扫描 只是 young generation 区域,并对其进行清理,如果有来自于 old generation 回到 young? 你需要准确地 "跟踪 "这些连接存在的位置--所以在扫描时 young generation 你可以在不破坏堆的情况下清理它。

想一想:你不能把一个对象标记为要移除的对象 A 现在年轻一代的人,如果有一个参照物的话 B 到它,从 old generation. 但请记住,现在 - 你是在年轻的收集 只是. 因此,为了跟踪这些 "连接",一个 Card Table 是实现的。这张牌表的每一个位子都表示老一代的某一部分是 "脏 "的,这意味着 也扫描那部分从老一代 而扫描年轻。

你为什么要这样做?扫描年轻人的全部目的是扫描一小部分,而不是全部。这个 card table 实现了。

G1 有区域。如果你在扫描 regionA 你会发现它有指向其他的 regionB? 只要把这些信息放在 Card Table 是不够的。您的牌桌只会知道 regionA下次你扫描的时候 regionB - 你怎么知道你应该扫描 regionA 也?如果你不这样做,显然堆的完整性被破坏了。

既然如此: remembered sets. 这些集合是由一个异步线程填充的:它扫描了 card table 并根据这些信息,它还会扫描这些 "肮脏 "区域的指针所在。它一直在跟踪这些 regionA -> regionB 连接。每个地区都有自己的 remembered set.

所以当你达到需要发生GC的时候,当扫描时 regionB 你也看看它的 remembered set 然后发现你还需要扫描 regionA.


在实践中,这就是为什么 G1 变得代代相传:这些 remembered sets 原来 巨大. 如果你把堆分成 youngold,没有必要保留年轻一代之间的联系,反正你一次扫描就可以了,这样就可以把这些套路大小的烧掉。G1 想要保留 200ms (默认)承诺--要做到这一点,你需要扫描年轻一代的 一下子 的区域之间没有联系(因为在 remembered sets 和,否则堆的完整性就没有了),但同时如果你把年轻一代的--尺寸做小了。remembered sets 将是大。

因此,触及这些设置,我认为是一个工程奇迹。