首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >正确使用GC.Collect();GC.WaitForPendingFinalizers();?

正确使用GC.Collect();GC.WaitForPendingFinalizers();?
EN

Stack Overflow用户
提问于 2012-09-04 14:26:18
回答 6查看 36.3K关注 0票数 39

我已经开始回顾一个项目中的一些代码,并发现如下所示:

代码语言:javascript
复制
GC.Collect();
GC.WaitForPendingFinalizers();

这些线条通常出现在在提高效率的理论基础下,用来破坏对象的方法上。我说过这句话:

  1. 在销毁每个对象时显式调用垃圾收集会降低性能,因为这样做不考虑对于CLR性能绝对必要的情况。
  2. 按该顺序调用这些指令将导致每个对象仅在其他对象正在完成时才被销毁。因此,一个可以独立销毁的物体必须等待另一个物体的毁灭,而不是真正的必要。
  3. 它可以生成死锁(请参阅:这个问题)

1,2和3是真的吗?你能提供一些参考来支持你的答案吗?

虽然我几乎肯定我的话,但我需要明确我的论点,以便向我的团队解释为什么这是一个问题。这就是我要求确认和证明的原因。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2012-09-04 14:42:16

简单的回答是:把它拿出来。这段代码几乎永远不会提高性能,也不会提高内存的长期使用。

你所有的观点都是真的。(它可以生成死锁;这并不意味着它总是死锁。)调用GC.Collect()将收集所有GC代的内存。这做了两件事。

  • 它每次都会收集所有世代的数据,而不是默认情况下GC将做什么,即只在满的时候收集一代人。典型的使用将看到Gen0收集(大约)是Gen1的十倍,而Gen1收集(大约)的频率是Gen2的十倍。这段代码每次都会收集所有代人。Gen0集合通常是100 is以下;Gen2可能要长得多。
  • 它将非收藏对象推广到下一代。也就是说,每次强制一个集合并且仍然有对某个对象的引用时,该对象将被提升到下一代。通常情况下,这种情况很少发生,但是下面这样的代码会更频繁地强制这样做: void SomeMethod() { object o1 =新对象();object o2 =新对象();o1.ToString();GC.Collect();//这迫使o2进入Gen1,因为它仍然被引用为o2.ToString()};

如果没有GC.Collect(),这两项都将在下一次机会时收集。如果集合是写的,o2将在Gen1中结束--这意味着自动的Gen0集合不会释放该内存。

还有一个更大的问题值得注意:在调试模式下,GC的功能不同,不会回收任何仍在作用域内的变量(即使在当前方法中以后没有使用)。因此,在调试模式下,上述代码在调用o1时甚至不会收集GC.Collect,因此o1o2都将被提升。在调试代码时,这可能会导致一些非常不稳定和意外的内存使用情况。(像这样的文章突出了这种行为。)

编辑:刚刚测试了这种行为,这是一个真正的讽刺:如果您有这样的方法:

代码语言:javascript
复制
void CleanUp(Thing someObject)
{
    someObject.TidyUp();
    someObject = null;
    GC.Collect();
    GC.WaitForPendingFinalizers(); 
}

..。然后它将显式地不释放someObject的内存,即使在发布模式下也是如此:它将把它提升到下一代GC中。

票数 35
EN

Stack Overflow用户

发布于 2012-09-04 14:41:24

有一点是很容易理解的:让GC运行可以自动清除每次运行的许多对象(例如,10000)。每次销毁后调用它,每次运行清理大约一个对象。

因为GC具有很高的开销(需要停止和启动线程,需要扫描所有活动的对象),批处理调用是非常可取的。

还有,清理完每一个物体会有什么好处呢?这怎么可能比分批更有效呢?

票数 8
EN

Stack Overflow用户

发布于 2012-09-05 00:10:31

你的第3点在技术上是正确的,但只有当某人在决赛中锁定时才能发生。

即使没有这样的呼叫,锁定在终结者内甚至比你在这里的情况还要糟糕。

有几次调用GC.Collect()确实有助于性能。

到目前为止,我已经做了2次,也许3次在我的职业生涯。(或者大概有5到6次,如果你包括了我做过的那些,测量结果,然后再取出来--这是你做完后应该是度量的东西)。

在这样的情况下,你在短时间内经历了数百或数千兆的记忆,然后在很长一段时间内转而使用不那么密集的记忆,这可能是一个巨大的、甚至是至关重要的改进。这就是这里发生的事吗?

在其他任何地方,他们最多只会让它变慢,并使用更多的内存。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12265598

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档