为什么CLR垃圾收集器的服务器模式比工作站模式占用更多内存?

时间:2014-12-29 16:44:35

标签: garbage-collection clr

我有以下测试,我在工作站模式和服务器模式下运行CLR垃圾收集器。在服务器模式结束时,我最终得到520 MB私有字节,在工作站模式下,我最终只有50 MB。这是windbg的输出结果:

!eeheap
...
...
GC Heap Size:            Size: 0x65ccac8 (106744520) bytes.


!address -summary
...
...
--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_FREE                                 53     7ffb`ae203000 ( 127.983 Tb)           99.99%
MEM_RESERVE                              94        4`31617000 (  16.772 Gb)  97.06%    0.01%
MEM_COMMIT                              

336 0`207d6000(519.836 Mb)2.94%0.00%

尽管在执行结束时我强制使用完整的GC,但导致这种差异的原因是什么呢?

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime;
using System.Threading;
using System.Threading.Tasks;
class Program
{
    static int N = 25 * 1000 * 1000;  // Execute allocations in a loop 25 million times
    static int Clear = 1000 * 1000;   // Clear list after every 1 million allocations to give GC 25 chances to clear things up

    static void Main(string[] args)
    {

        // do some warmup
        AllocateRefContainer();
        GC.Collect();
        GC.Collect();

        var sw = Stopwatch.StartNew();
        AllocateRefContainer();
        sw.Stop();
        Console.WriteLine("RefContainer Allocation {0:F2}s, {1:N0} Allocs/s", sw.Elapsed.TotalSeconds, N / sw.Elapsed.TotalSeconds);

        GC.Collect();
        GC.Collect(2, GCCollectionMode.Forced, true);
        Thread.Sleep(1000);
        Console.WriteLine("PooledRefContainer Allocation {0:F2}s, {1:N0} Allocs/s", sw.Elapsed.TotalSeconds, N / sw.Elapsed.TotalSeconds);
        Console.WriteLine("Private Bytes: {0:N0} MB", Process.GetCurrentProcess().PrivateMemorySize64 / (1024 * 1024));

        Console.ReadLine();
    }

    class ReferenceContainer // Class with one object reference
    {
        public ReferenceContainer Obj;
    }

    static List<ReferenceContainer> RContainer = new List<ReferenceContainer>();
    static void AllocateRefContainer()
    {
        var container = RContainer;
        for (int i = 0; i < N; i++)
        {
            container.Add(new ReferenceContainer());
            Calculate();
            if (i % Clear == 0)
            {
                container.Clear();
            }
        }
    }

    // Simulate some CPU only calculation
    static void Calculate()
    {
        long lret = 0;
        for (int i = 0; i < 100; i++)
        {
            lret++;
        }
    }

}

1 个答案:

答案 0 :(得分:0)

服务器模式为每个逻辑处理器核心运行1个GC线程。该线程被分配了自己的工作集。因此,如果你有8个核心,那么开销大约是8倍。 GC也是非确定性的,因此您无法可靠地评估内存使用情况,因为报告的字节是应用程序的保留,而不是那些使用的。服务器GC更具侵略性,可以保留更多字节。

See this MSDN article了解更多信息。