Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this memory not get cleaned up, or get allocated at all?

So, I've got this awesome program that is very useful:

static void Main(string[] args)
{
    new Dictionary<int,int>(10000000);

    while (true)
    {
        System.Threading.Thread.Sleep(1000);
    }
}

This doesn't even produce any warnings from the compiler, which is surprising.

Running this allocates a chunk of memory. If I run several copies, I'll eventually get to a point where I can't start any more because I've run out of memory.

  1. Why doesn't the garbage collector ever clean up the memory, instead letting the system get into a state where there is not enough memory for new processes?
  2. Heck, why isn't the memory allocation optimized out? It can never be referenced by anything ever!

So what's going on here?

like image 212
Joe Avatar asked Feb 26 '23 14:02

Joe


1 Answers

The garbage collector is non-deterministic, and responds to memory pressure. If nothing requires the memory, it might not collect for a while. It can't optimize away the new, as that changes your code: the constructor could have side-effects. Also, in debug it is even more likely to decide not to collect.

In a release/optimized build, I would expect this to collect at some point when there is a good reason to. There is also GC.Collect, but that should generally be avoided except for extreme scenarios or certain profiling demands.

As a "why" - there is a difference in the GC behaviour between GC "generations"; and you have some big arrays on the "large object heap" (LOH). This LOH is pretty expensive to keep checking, which may explain further why it is so reluctant.

like image 78
Marc Gravell Avatar answered Apr 30 '23 12:04

Marc Gravell