不受欢迎的垃圾收集

时间:2012-01-05 17:58:34

标签: c# .net garbage-collection

标题“强制垃圾收集”来自书籍“C#2010和.NET 4平台”由Andrew Troelsen撰写:

“再一次,.NET垃圾收集器的全部目的是代表我们管理内存。但是,在一些非常罕见的情况下,使用GC.Collect()以编程方式强制垃圾收集可能是有益的。具体来说:

•您的应用程序即将进入一个您不希望被可能的垃圾回收中断的代码块。 ... “

但是停下来!垃圾收集是不合需要的吗?我从来没有看过/读过这样的东西(因为我的开发经验很少)。如果您在练习时已经做过类似的事情,请分享。对我而言,这是非常有趣的一点。

谢谢!

6 个答案:

答案 0 :(得分:7)

是的,在垃圾收集不受欢迎的情况下绝对存在这样的情况:当用户等待某事发生时,他们必须等待更长时间,因为代码无法继续,直到垃圾收集完成。

Troelsen指出:如果你有一个特定的点,你知道GC 有问题并且可能能够收集大量的垃圾然后它可能然后挑起它,以避免它在不太合适的时刻触发。

答案 1 :(得分:5)

我运行一个与食谱相关的网站,并在内存中存储大量食谱及其成分用量的图表。由于我将这些信息转换为快速访问的方式,我必须在应用程序加载之前将几个数据库加载到内存中,然后才能将数据组织到一个非常优化的图形中。我在堆上创建了大量的小对象,一旦构建了图形,就会无法访问。

这是在Web应用程序加载时完成的,可能需要4-5秒才能完成。在我这样做之后,我打电话给GC.Collect();,因为我现在宁愿重新声明所有内存,而不是在传入的HTTP请求期间阻止所有线程,而垃圾收集器却吓坏了清理所有这些短暂的对象。我还认为现在最好清理,因为此时堆可能不那么碎片化,因为到目前为止我的应用程序还没有真正完成任何其他操作。延迟这种情况可能会导致创建更多对象,并且当GC自动运行时需要对堆进行更多压缩。

除此之外,在我12年的.NET编程中,我从未遇到过我想强制垃圾收集器运行的情况。

答案 2 :(得分:3)

建议您不要在代码中明确调用Collect。你能找到有用的情况吗?

其他人已经详细介绍了一些,毫无疑问更多。首先要理解的是,不要这样做。这是最后的选择,调查其他选项,了解GC如何处理您的代码受影响的方式,遵循您的设计的最佳实践。

在错误的位置拨打Collect会让您的表现更糟。更糟糕的是,依靠它会使你的代码非常脆弱。通过对代码进行简单更改,可以完全取消调用Collect有用或最终无害的罕见条件,这将导致意外的OOM,缓慢的性能等。

答案 3 :(得分:2)

我在性能测量之前调用它,以便GC不会伪造结果。

另一种情况是测试内存泄漏的单元测试:

object doesItLeak = /*...*/; //The object you want to have tested
WeakReference reference = new WeakRefrence(doesItLeak); 
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

Assert.That(!reference.IsAlive);

除此之外,我没有遇到实际上有用的情况 特别是在生产代码中,永远不应该找到GC.Collect恕我直言。

答案 4 :(得分:1)

这将是非常罕见的,但GC可能是一个中等昂贵的过程,所以如果有一个特定部分的时间敏感,你不希望GC部分中断该部分。

答案 5 :(得分:1)

  

您的应用程序即将进入您不需要的代码块   想要被可能的垃圾收集打断。 ...

一个非常可疑的论点(尽管如此使用了很多)。

Windows不是实时操作系统。您的代码(线程/进程)始终可以被OS调度程序抢占。您无权保证访问CPU。

所以归结为:GC运行的时间与时隙(~20 ms)相比如何?

关于这方面的硬数据非常少,我搜索了几次。

根据我自己的观察(非常非正式),gen-0集合是< 40毫秒,通常少很多。一个完整的gen-2可能会遇到~100 ms,可能更多。

因此被GC中断的'风险'与换出另一个过程的风险程度相同。你无法控制后者。