Is GC.Collect() blocking?

本文关键字:blocking GC Collect Is | 更新日期: 2023-09-27 17:59:49

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

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

Is GC.Collect() blocking?

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

无论如何,如果它确实启动了垃圾回收,那么在开始基准测试之前,您应该等待所有的finizer完成。

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

因为。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。收集方法(Int32,GCCollectionMode,布尔)

MSDN:诱导收集-引导

如果您想对代码进行基准测试,应该在多次迭代的过程中进行,并作为平均值。当GC在第一时间运行时,您永远无法得到保证。

您应该假设:

  1. GC运行一些时间,而不是其他时间
  2. 沉重的事情有时发生在一些不相关的过程中,而不是发生在其他一些过程中
  3. 偶尔会发生一些疯狂的事情

因此,对您正在进行的测试进行几次迭代,删除最高和最低的测试(假设它们都是侥幸),并对剩余的测试进行平均。这将为您提供有意义的比较。

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

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

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

也就是说,没有办法确保GC不会运行。我不明白为什么要这么做。例如,如果你的代码创建了很多临时对象,GC应该是你的基准测试的一部分,无论好坏,你都不应该试图排除它