Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does c# remove the memory allocated in loop?

Tags:

c#

imagine this code:

int i=9999999;
while ( i > 1 )
{
    string UnusedMemory="this is a string that eats some ram" + i.ToString();
    i--;
}

if unreferenced objects were removed only sometimes when GC.Collect() is run, this code should allocate lot of ram until collect happen. But it doesn't allocate huge memory at all, why? Is there some kind of "delete" implemented on IL level? Or is GC.Collect() called automatically faster? I know this is a trivial example, but if it was more complicated and string was accessed in that block of code, it wouldn't eat lot of ram anyway.

EDIT: I changed the example so that string is always unique, so that it can't be "cached"

like image 920
Petr Avatar asked Aug 31 '25 03:08

Petr


2 Answers

String constants are "cached" in a string pool, so it's the same string each time.

If you use the method String.IsInterned on the string, then it will return true which means it's contained in the pool.

From String.IsInterned:

The common language runtime automatically maintains a table, called the intern pool, which contains a single instance of each unique literal string constant declared in a program, as well as any unique instance of String you add programmatically.

The intern pool conserves string storage. If you assign a literal string constant to several variables, each variable is set to reference the same constant in the intern pool instead of referencing several different instances of String that have identical values.

Furthermore, the GC is automatically called when memory are needed or enough elements have been allocated, so even if strings weren't cached then it wouldn't be a problem.

From Fundamentals of Garbage Collection:

Garbage collection occurs when one of the following conditions is true:

  • The system has low physical memory.
  • The memory that is used by allocated objects on the managed heap surpasses an acceptable threshold. This means that a threshold of acceptable memory usage has been exceeded on the managed heap. This threshold is continuously adjusted as the process runs.
  • The GC.Collect method is called. In almost all cases, you do not have to call this method, because the garbage collector runs continuously. This method is primarily used for unique situations and testing.

Is it possible to change this behavior or optimize it? Yes, to some extend: Latency Modes

This question is very much related to: C# memory usage for creating objects in a for loop

like image 164
Lasse Espeholt Avatar answered Sep 02 '25 16:09

Lasse Espeholt


When an object is allocated from the heap, and there isn't enough free space, the garbage collector will run. If a collection of the first heap doesn't free enough memory it will continue to do collections on the next level heap. Only if collection of all heaps doesn't release enough memory, it will allocate more memory from the system.

As there are a lot of recently freed objects in your example, the collection of the first heap will always free enough memory. Your loop will fill the heap several times. You can print out GC.CollectionCount(0) before and after the loop to see how many times it did run.

like image 39
Guffa Avatar answered Sep 02 '25 15:09

Guffa