【发布时间】:2017-12-26 21:10:03
【问题描述】:
假设我有一个像这样的 C# 方法:(显然不是真正的代码)
byte[] foo()
{
var a = MethodThatReturns500mbObject();
var b = MethodThatReturns200mbObject(a);
byte[] c = MethodThatReturns150mbByteArray(b);
byte[] d = UnwiselyCopyThatHugeArray(c);
return d;
}
正如您可以通过命名猜到的那样,这些方法返回的对象是巨大的。每个对象需要数百兆的总 RAM,尽管前两个对象由数百万个较小的对象组成,而不是像后两个数组那样是一个巨大的块。
我们将很快将其优化为流式解决方案,但与此同时,我想确保至少我们不会在执行代码以生成后期对象时阻止早期对象的 GC。
我的问题是:只要 MethodThatReturns200mbObject(a) 返回,对象a 是否有资格获得 GC?如果没有,让 GC 知道有 500MB 的存在等待它的最佳方法是什么?
我的问题的核心是.NET GC 判断“这个对象没有引用”是否足够聪明,知道a 在MethodThatReturns200mbObject(a) 返回后不能被引用。尽管var a 理论上仍然可用于以后的代码,但a 在方法第二行以下的任何地方都不会被引用。理论上,编译器可以让 GC 知道 a 未被引用。但在实践中,我不确定它的行为方式。你知道吗?
【问题讨论】:
-
GC.KeepAlive()如果所有变量在其作用域结束前都已保持活动状态,则不会有太大用处。 -
在发布模式下,是的,编译器足够聪明,可以在不再使用
a时将其标记为垃圾回收的候选对象。 This answer 也可能有用
标签: c# .net memory-management garbage-collection large-object-heap