.NET中的垃圾收集(代)

我已经阅读了很多.NET性能文章,这些文章描述了Gen1,Gen2垃圾收集和几代人幸存的对象。

为什么对象能够在收集中存活?

什么是钉扎?

我如何了解更多相关信息?

在垃圾收集器中有多代的一个原因是避免将内存丢失到碎片。

每个函数调用都可能意味着多个对象的创建和删除集合,因此程序的内存堆往往会很快崩溃。 这留下了不太实用的漏洞。 结果是您的程序需要定期拆分,就像硬盘一样。 这是收集过程中发生的一部分。

当一个物体在一个集合中存活下来时,它被转移到一个更长寿的一代,理论上如果它在一个集合中幸存下来,它可能会在其他集合中存活下来。 因此,后代的转换次数较少,并且不会碎片化。 这意味着你的程序花费更少的时间来整理周围的东西以清理漏洞并浪费更少的内存。 这也是对传统内存管理(malloc / free或new / delete)的改进,后者将其留给操作系统来管理任何内存碎片。

对象在收集中存活的原因是因为某些地方仍然处于“范围内”并且持有对该对象的引用。 有几种方法可以导致这种情况发生,然后忘记引用,因此可以在托管代码中“泄漏”内存。

有时人们很想调用GC.Collect()来努力让垃圾收集器清理一些东西。 也许他们发现他们有泄漏,或者认为记忆变得过于分散。 你应该抵制那些冲动。 虽然.Net中的垃圾收集并不完美,但它是非常好的,而且它几乎肯定比清理内存要好得多。 可能的情况是,如果一个物体可以而且应该被收集,那就是。 请记住,调用GC.Collect()实际上可以通过帮助垃圾收集器将对象移动到更高的一代来使事情变得更糟,从而使它们保持更长时间。

相反,如果您怀疑自己有泄漏,请查看您自己的代码,以查找可能包含对许多其他项的引用的全局变量或静态变量。 你应该调用GC.Collect()的唯一一次是你有关于垃圾收集器不可用的程序性质的信息,而且这很少见,因为GC知道你创建的每个引用。

“Pinning”适用于需要将对象传递给非托管库的情况。 垃圾收集器可以将对象的物理位置移动到内存中,因此您需要在一个位置“固定”它,否则非托管库使用的指针可能会变为无效。 固定的对象无法收集,因此您不应将对象固定超过必要的时间。

http://blogs.msdn.com/maoni/是一个很好的资源。
在这里问问题也有帮助:)

对于你的问题:

为什么对象在集合中存活:
当对象是“活动对象”或“可到达对象”时,它们会在集合中存活。 可到达对象是从另一个对象引用它们的对象:

  1. 堆栈
  2. 终结队列
  3. 更高代的另一个对象(例如,Gen2对象持有对Gen0对象的引用)
  4. 句柄表(CLR使用的数据结构,需要单独的post:))

什么是钉扎:
固定意味着确保对象不会在内存中移动。 由于压缩GC,对象在内存中移动,如果要固定对象,可以创建类型为固定的GCHandle,对于通过PInvoke传递给本机代码的对象,也会自动在sciene后面进行固定(如同字符串一样)作为输出传递,内部缓冲区在调用PInvoke期间被固定。

查看http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.gchandle.aspx ,了解有关GCHandle的一个很好的例子。

这是一个简短但完整的程序,我写的是在正在运行的应用程序中演示第2代垃圾收集

http://nomorehacks.wordpress.com/2008/11/27/forcing-the-garbage-collector/

我觉得这篇文章也很好。

http://msdn.microsoft.com/en-us/library/ms973837.aspx

非常大的话题。 以上是MS的一个很好的总结。

这是一篇有关该主题的有趣文章,您可能会发现这些文章内容丰富。

固定用于防止垃圾收集器重定位对象。 它可以通过限制垃圾收集器可以执行的操作来损害性能。 通常,固定物体的固定时间应尽可能短。