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"
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:
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With