我已经开始回顾一个项目中的一些代码,并发现如下所示:
GC.Collect();
GC.WaitForPendingFinalizers();这些线条通常出现在在提高效率的理论基础下,用来破坏对象的方法上。我说过这句话:
1,2和3是真的吗?你能提供一些参考来支持你的答案吗?
虽然我几乎肯定我的话,但我需要明确我的论点,以便向我的团队解释为什么这是一个问题。这就是我要求确认和证明的原因。
发布于 2012-09-04 14:42:16
简单的回答是:把它拿出来。这段代码几乎永远不会提高性能,也不会提高内存的长期使用。
你所有的观点都是真的。(它可以生成死锁;这并不意味着它总是死锁。)调用GC.Collect()将收集所有GC代的内存。这做了两件事。
如果没有GC.Collect(),这两项都将在下一次机会时收集。如果集合是写的,o2将在Gen1中结束--这意味着自动的Gen0集合不会释放该内存。
还有一个更大的问题值得注意:在调试模式下,GC的功能不同,不会回收任何仍在作用域内的变量(即使在当前方法中以后没有使用)。因此,在调试模式下,上述代码在调用o1时甚至不会收集GC.Collect,因此o1和o2都将被提升。在调试代码时,这可能会导致一些非常不稳定和意外的内存使用情况。(像这这样的文章突出了这种行为。)
编辑:刚刚测试了这种行为,这是一个真正的讽刺:如果您有这样的方法:
void CleanUp(Thing someObject)
{
someObject.TidyUp();
someObject = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}..。然后它将显式地不释放someObject的内存,即使在发布模式下也是如此:它将把它提升到下一代GC中。
发布于 2012-09-04 14:41:24
有一点是很容易理解的:让GC运行可以自动清除每次运行的许多对象(例如,10000)。每次销毁后调用它,每次运行清理大约一个对象。
因为GC具有很高的开销(需要停止和启动线程,需要扫描所有活动的对象),批处理调用是非常可取的。
还有,清理完每一个物体会有什么好处呢?这怎么可能比分批更有效呢?
发布于 2012-09-05 00:10:31
你的第3点在技术上是正确的,但只有当某人在决赛中锁定时才能发生。
即使没有这样的呼叫,锁定在终结者内甚至比你在这里的情况还要糟糕。
有几次调用GC.Collect()确实有助于性能。
到目前为止,我已经做了2次,也许3次在我的职业生涯。(或者大概有5到6次,如果你包括了我做过的那些,测量结果,然后再取出来--这是你做完后应该是度量的东西)。
在这样的情况下,你在短时间内经历了数百或数千兆的记忆,然后在很长一段时间内转而使用不那么密集的记忆,这可能是一个巨大的、甚至是至关重要的改进。这就是这里发生的事吗?
在其他任何地方,他们最多只会让它变慢,并使用更多的内存。
https://stackoverflow.com/questions/12265598
复制相似问题