title: Why does server mode of CLR garbage collector occupies more memory than workstation mode?
body: <p>I have the below test that I run in workstation mode and server mode for CLR garbage collector. At the end in server mode I end up with 520 MB private bytes where as in workstation mode, I only end up with 50 MB. Here's my output from windbg:</p>
  
  <pre><code>!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                              
  </code></pre>
  
  <p>336        0`207d6000 ( 519.836 Mb)   2.94%    0.00%</p>
  
  <p>What is the thing causes that big difference despite the fact that at the end of the execution I force full GC?</p>
  
  <pre><code>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&lt;ReferenceContainer&gt; RContainer = new List&lt;ReferenceContainer&gt;();
      static void AllocateRefContainer()
      {
          var container = RContainer;
          for (int i = 0; i &lt; 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 &lt; 100; i++)
          {
              lret++;
          }
      }
  
  }
  </code></pre>