GC何时决定收集第2代?

时间:2011-12-20 21:14:00

标签: .net garbage-collection

在白天,我在Windows服务中看到了很多第2代收藏。

GC何时决定进行完全收集而不是仅收集Gen1和Gen0或仅收集Gen0?

2 个答案:

答案 0 :(得分:9)

阅读http://msdn.microsoft.com/en-us/library/0xy59wtx.aspx和相关文章了解详情。一般来说,gen2是在“必要时”收集的。

可能导致过多Gen2集合的一件事是大对象堆(LOH)。当LOH被填满时,它将触发完整的收集。如果您的应用程序分配并释放大量大型对象(80K或更大),那很可能是您的问题。

请参阅CLR Inside Out: Large Object Heap Uncovered

还要考虑在服务中使用服务器垃圾收集器。它通常会提供更好的性能(更少的集合)。将其添加到app.config文件中:

<configuration
   <runtime>
      <gcServer enabled="true"/>
   </runtime>
</configuration> 

答案 1 :(得分:5)

通常在满足以下一项时触发(在任何一代下)

  • 分配超过阈值。我认为这是基于当前需求的动态。任何人都可以确认/否认吗?
  • 内存不足情况
  • 通过GC.Collect()
  • 调用

可能还有另一种我不知道的情况,但通常就是这样。第一个是通常开始收集的东西,而且相对来说,收集G2比G0更加昂贵,你会看到更少的收藏。


解决评论中的问题:
每一代都有一个阈值,当命中时会触发一个集合。 Gen0可以是5mb,并且在填充时将被触发。 GC运行后,如果仍然在那里有5mb,我相信它会增加限制。如果不是每个分配都会触发一个集合,那么你就有问题了。 Gen2 可以为20mb(注意我在这里编号)并且在那里应用相同的逻辑。

对于教科书示例,让我们看一个简单的场景。

  1. 新的应用分配对象和所有放在Gen0中,总共3MB的数据。 (这是总是如此,但假装它是)
  2. GC命中,其中1 MB移动到G1,其余部分被清理干净。
  3. G0现在免费,G1有1MB。
  4. 创建了更多对象,并且会发生更多GC。过了一会儿G1充满了,有些人搬到了G2。
  5. 对象保持不变直到G2已满,然后如果不使用则将其清除。如果仍然引用某个对象,它将保留在G2中,直到可以清除
  6. 一个完整的GC是昂贵的,我已经看到几天没有发生。当然这是在一个具有> 64GB ram的系统上,并且没有必要。