Search code examples
c#memorygarbage

CG.Collect doesn't work in my big app, but works fine in a small project


When I put this code in a small Console project:

Console.WriteLine($"Mémoire avant allocation 1G: {GC.GetTotalMemory(false)}");

byte[] buf = new byte[1000000000];

Console.WriteLine($"Mémoire après allocation 1G: {GC.GetTotalMemory(false)}");

buf = null;

GC.Collect();

GC.WaitForPendingFinalizers();

GC.Collect();

Console.WriteLine($"Mémoire après libération 1G: {GC.GetTotalMemory(false)}");

I get the Following result (as expected):

  Mémoire avant allocation 1G: 30028

  Mémoire après allocation 1G: 1000038252

  Mémoire après libération 1G: 29472

Now the very same code in the big Application I'm working on, I get this result:

Mémoire avant allocation 1G: 153152496

Mémoire après allocation 1G: 1153152552

Mémoire après libération 1G: 1146813960

As you can see, GC.Collect does nothing here.

Why is that?


Solution

  • Try compacting the LOH

    GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
    GC.Collect( );
    

    Also note that the documentation describing GC.Collect( ) always uses the word "tries" or "try".

    Example (emphasis mine):

    Use this method to try to reclaim all memory that is inaccessible. It performs a blocking garbage collection of all generations.

    All objects, regardless of how long they have been in memory, are considered for collection; however, objects that are referenced in managed code are not collected. Use this method to force the system to try to reclaim the maximum amount of available memory.