GC.Collect()阻塞了吗?

时间:2011-06-18 22:43:28

标签: c# garbage-collection

我正在对我的代码运行一些基准测试,我想确保在我的一个基准测试期间不会发生垃圾收集,因为它正在清理先前测试的混乱。我认为我的最好的机会是在开始基准测试之前强制收集。

所以我在基准测试开始之前调用GC.Collect(),但不确定收集是否继续在单独的线程中运行等,并立即返回。如果它确实在BG线程上运行,我想知道如何同步调用它或者至少等待它完成收集。

5 个答案:

答案 0 :(得分:11)

正如MSDN所述 - 使用此方法尝试来回收所有无法访问的内存。

无论如何,如果确实启动了垃圾收集,你应该等到所有的终结者完成开始基准测试之前。

   GC.Collect();

   GC.WaitForPendingFinalizers();

答案 1 :(得分:10)

.NET Framework 4.5 ,您可以指定GC集合是否应该阻止:

GC.Collect(GC.MaxGeneration, GCCollectionMode.Optimized, blocking: true);

GC.Collect(GC.MaxGeneration, GCCollectionMode.Default, blocking: true);

GCCollectionMode.Default目前默认为GCCollectionMode.Forced

有关详细信息,请参阅:

MSDN: GC.Collect Method (Int32, GCCollectionMode, Boolean)

MSDN: Induced collections - guide

答案 2 :(得分:2)

如果您想对代码进行基准测试,则应该在多次迭代过程中进行平均分析。首先运行GC时,您永远无法保证。

答案 3 :(得分:2)

你应该假设:

  1. GC运行一段时间,而不是其他一些。
  2. 有些时候,某些不相关的过程会发生沉重的事情,而不是其他一些过程。
  3. 偶尔会发生一些疯狂的事情。
  4. 因此,你要做的几次迭代测试,删除最高和最低(假设它们都是吸虫)并平均剩下的。这将为您提供有意义的比较。

答案 4 :(得分:-1)

.Net中GC的工作方式是停止所有线程(至少是完整集合的一部分,这是GC.Collect()所做的)。所以你可以说它是非常同步的,它不是只阻止一个线程,而是所有线程。调用GC.Collect()将执行收集并在完成后返回,因此,GC.Collect() 同步运行它的方式。

有一个与GC相关的部分在后台线程上运行 - 终结器。如果要在运行基准测试之前确保所有终结器都已完成,并且实际收集了所有已完成的对象,请使用:

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

话虽如此,没有办法确保GC不会运行。我不明白为什么要那样做。例如,如果您的代码创建了大量临时对象,那么GC应该是您的基准测试的一部分,无论好坏,您都不应该尝试排除它。