GC.Collect()和GC.Collect(GC.MaxGeneration)之间有什么区别?

3

我看到多篇答案建议运行GC.Collect(GC.MaxGeneration)

由于方法GC.Collect()将收集所有现有的代,这两者之间有什么区别吗?

也许如果存在的是两个代而不是三个代,GC将收集两个代,并且不会尝试收集第三代,这将提高性能。 但是,这真的有意义吗?

5个回答

2
唯一的区别在于GC.Collect()将使用GCCollectionMode.Optimized,而GC.Collect(GC.MaxGeneration)将使用GCCollectionMode.Default(至少在.NET Framework 4.5中)。还有一些重载可以手动指定收集模式。
/// <summary>Specifies the behavior for a forced garbage collection.</summary>
public enum GCCollectionMode
{
    /// <summary>The default setting for this enumeration, which is currently <see cref="F:System.GCCollectionMode.Forced" />. </summary>
    Default,
    /// <summary>Forces the garbage collection to occur immediately.</summary>
    Forced,
    /// <summary>Allows the garbage collector to determine whether the current time is optimal to reclaim objects. </summary>
    Optimized
}

你确定他们使用不同的模式吗?我认为他们两个都使用默认+阻塞。 - CodesInChaos
1
GC.Collect()使用默认模式。您可以使用ilspy等工具进行检查。看起来唯一的区别是_Collect(GC.MaxGeneration,0)与_Collection(-1,0)。 - Will
@CodesInChaos - 是的,我刚刚在ILSpy中查看了源代码。 - Knaģis
也许你可以链接到这里:http://msdn.microsoft.com/en-us/library/bb495757.aspx - V4Vendetta

1

GC.Collect()可能不会起作用,因为它使用“优化”进行GCCollectionMode。

MSDN中的Optimized->允许垃圾回收器确定当前时间是否最适合回收对象。

GC.Collect(GC.MaxGeneration)使用“强制”进行GCCollectionMode

MSDN中的Forced->立即强制进行垃圾回收。

两种方法都会尝试恢复所有代。


0

标准(系统启动的)垃圾回收的行为如下:

  1. 从GenX中删除所有未根源的项目(即从活动代码引用)
  2. 将所有剩余的项目从GenX提升到GenX+1
  3. 如果GenX+1中没有足够的空间容纳新项目,则重复上述步骤

因此,标准收集可能仅收集Gen0,并将一些数据移动到Gen1,然后停止。这有助于达到Gen2的对象的长寿命:Gen2比Gen0更不经常被收集,因此达到Gen2的对象可能会挂起一段时间。

如果强制对所有代进行收集,则Gen2中的对象将立即被收集。这将释放更多内存,但也会影响性能。

最重要的是,任何收集都会将根源项目提升到下一代。这是手动收集不好的原因之一:项目将不必要地被提升到Gen1/2,然后实际上会挂起更长时间(除非您反复使用手动GC,这只会加剧问题...)。


值得注意的是,在上一次Gen1收集后未被写入的Gen1或Gen2中的对象不可能包含任何Gen0中的对象,因此在Gen0收集期间可以完全忽略它们。同样,在上一次Gen2收集后未被写入的Gen2中的对象不可能包含任何Gen0或Gen1中的对象,因此在Gen0或Gen1收集期间可以完全忽略它们。利用未被写入的Gen1和Gen2对象不需要被检查的事实是实现分代GC性能的最大关键。 - supercat

0

GC.Collect() 使用 GCCollectionMode.Default,而 GC.Collect(GC.MaxGeneration) 也是这样。

因此它们之间没有区别!


根据MSDN
GCCollectionMode枚举
默认:此枚举的默认设置,目前为Forced。 强制:立即强制进行垃圾回收。 优化:允许垃圾收集器确定当前时间是否最适合回收对象。
使用Reflector:
[MethodImpl(MethodImplOptions.InternalCall)]
private static void nativeCollectGeneration(int generation, int mode); 

public static void Collect()
{
  GC.nativeCollectGeneration(-1, 0);
}

public static void Collect(int generation)
{
  GC.Collect(generation, GCCollectionMode.Default);
}

附言:0GCCollectionMode.Default 是相同的。


似乎在不同的.NET框架版本中使用的枚举值是不同的,您查看的是哪个.NET框架版本? - Knaģis

-1

这是GC类的内部代码

// Forces a collection of all generations from 0 through Generation.
//
public static void Collect(int generation) {
    Collect(generation, GCCollectionMode.Default);
    }

// Garbage Collect all generations.
//
[System.Security.SecuritySafeCritical]  // auto-generated
public static void Collect() {
    //-1 says to GC all generations.
    _Collect(-1, (int)GCCollectionMode.Default);
}

[System.Security.SecuritySafeCritical]  // auto-generated
public static void Collect(int generation, GCCollectionMode mode)
{
    if (generation<0)
    {
        throw new ArgumentOutOfRangeException("generation", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
    }
    if ((mode < GCCollectionMode.Default) || (mode > GCCollectionMode.Optimized))
    {
        throw new ArgumentOutOfRangeException(Environment.GetResourceString("ArgumentOutOfRange_Enum"));
    }
    Contract.EndContractBlock();
    _Collect(generation, (int)mode);
}

在这里,您可以看到两个方法调用都使用了两个参数调用Collect方法。Collect(int genration,GCCollectionMode mode)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接