假设我有一个像这样的 C# 方法:(显然不是真正的代码)
byte[] foo()
{
var a = MethodThatReturns500mbObject();
var b = MethodThatReturns200mbObject(a);
byte[] c = MethodThatReturns150mbByteArray(b);
byte[] d = UnwiselyCopyThatHugeArray(c);
return d;
}
正如您可以通过命名猜到的那样,这些方法返回的对象是巨大的。每个对象需要数百兆的总 RAM,尽管前两个对象由数百万个较小的对象组成,而不是像后两个数组那样是一个巨大的块。
我们将很快将其优化为流式解决方案,但与此同时,我想确保至少在执行代码以生成较晚的对象时,我们不会阻止早期对象的 GC。
我的问题是:a
只要 MethodThatReturns200mbObject(a) 返回,对象是否有资格获得 GC?如果没有,让 GC 知道有 500MB 的存在等待它的最佳方法是什么?
我的问题的核心是.NET GC 对“这个对象没有引用”的判断是否足够聪明,知道返回a
后不能引用MethodThatReturns200mbObject(a)
。尽管var a
理论上仍然可用于以后的代码,a
但在方法的第二行下方的任何地方都不会引用。理论上,编译器可以让 GC 知道a
没有引用。但在实践中,我不确定它的行为方式。你知道吗?