第三代对象和大对象堆之间的区别

4
大对象堆和第三代GC对象有什么区别?

是的,如果从0 1 2..开始计数,则是第二个。 - Ravi Sharma
1个回答

19
LOH(大对象堆)是一个单独的堆,大对象直接在其中分配并保留,直到被回收。对象根据其大小直接分配到LOH中,例如大小等于或大于85000字节。
分代对象是分配到SOH(小对象堆)中的“小”对象,它是一个单一的堆。 SOH中的对象具有关联的代数,表示它们已经存活了多少次垃圾回收,最多到达最大代数,例如2。由于代数从0开始计数,因此代数为2的对象可以描述为第3代,因为它至少经历了3次垃圾回收,即第0、1、2代。
代数有助于优化垃圾扫描。长时间存活的对象随着它们存活的垃圾回收而增加其代数,具有更高代数的代数扫描频率较低。该机制导致不是短寿命的对象扫描频率较低,因此不必要。代际方案适用于SOH,因为它被视为堆中存在许多对象的良好优化。
更新
据我所知,LOH对象报告为在最大代中,但我认为这只是默认值。它们实际上不在任何代中,即第2代SOH对象和LOH对象不在同一个“列表”中。但是,正如@Henk指出的那样,在执行第2代收集时,LOH对象也会被收集。因此,代数2和LOH之间存在概念上的关系。这在.Net 2.0中是正确的。

请参考: 大对象堆揭秘

从代的角度来看,大对象属于第二代,因为只有进行第二代垃圾回收时才会对其进行回收。

然而,尽管有这种回收关系,但在进行代压缩时可能存在不成立的情况。当对一个代进行回收时,可能还会进行压缩。但是,LOH并没有被压缩,因此不能说发生在第二代对象上的所有事情都会发生在LOH中的对象上。

[Test]
public void large_object_heap_objects_are_reported_as_max_generation()
{
    int[] bling = new int[85000 / 4];

    int maxGen = GC.MaxGeneration;
    int objectGen = GC.GetGeneration(bling);

    Assert.AreEqual(maxGen, objectGen, "Large object is at max generation.");
}

那么,大小超过85kb的对象总是进入LOH而不是SOH,这就是规则? - Ravi Sharma
@Ravi 对象是否进入 LOH 取决于其大小,但规则并未公开,并且没有 API 可以推导这些规则。然而,有一个经常被提及的规则是对象大于 85000 字节(不是 85k)。同样,这些规则无法通过 API 发现。我已经稍微更新了我的问题。 - Tim Lloyd
谢谢您,chibacity,解释得很好。 - Ravi Sharma
@Henk 我的理解是,LOH对象实际上并不在第二代中,因为第二代有一个对象列表,其中包括LOH和SOH对象。而这只是一个概念上的区分。我明白这很微妙 - 我的更新还不太正确。我认为指出LOH对象实际上并不在第二代中是正确的,并值得注意。下次我使用电脑时会更新我的答案。谢谢。 - Tim Lloyd
这是一篇旧文章,但从.NET 4.5.1开始,虽然默认情况下LOH对象仍不会在第二代压缩时被压缩,但您实际上可以通过使用GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;来实现这一点。 - Lexi Tramel
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接