.NET GC Myth #2 -- The GC Frees Memory

.NET GC Myth #2 -- The GC Frees Memory

.NET Garbage Collection Myth #2:

The .NET Garbage Collector frequently removes unreferenced objects and frees their memory for other processes.

Fact:

The .NET Garbage Collector frequently removed unreferenced objects and reserves their memory for the same process.

Details:

Yes, the .NET GC is frequently removing your objects that are no longer referenced (actually unreachable is the term), but that's not the whole story.  The .NET memory manager grabs memory in large chunks and reserves them so that it doesn't have to keep getting lots of small blocks of memory very often.  This is a very good practice, especially when there is plenty of memory available, since getting memory allocated from the OS does take time.  This means that your application may start with 16MB that is dedicated to it, even though its only using 2MB -- note that the number may be different on your system.  Then when you finally get to needing 17MB, it will go out and grab another chunk, so that now you have 32MB (or some other number again) reserved for your application.  Now, what happens when the GC frees up memory and you now are back to only needing 2MB?  The GC may have removed your objects, and reduced your committed memory, but the reserved memory will not get reduced since it makes the reasonable assumption that you may need it again.  Again, this is a great principal for most systems on today's computers with lots of memory, but there are situations where you need to be aware of this and manage it accordingly.  The situations I'm thinking of are when there are multiple systems all competing for the same total memory, like my Citrix cases recently, or web servers when each web app is configured as a separate appdomain, or your individual computer if you run lots of programs at once.  How can you better manage for this?  By helping the GC remove objects as quickly as possible so it doesn't have to keep reserving more memory.  You can do this by keeping as many objects local to methods as possible, and also by setting objects to null if they are relatively large and you're done with them.  Finally, when does memory actually get freed?  I can't say conclusively that this is the only occassion, although it may be, but the OS sends a low memory resource notification event that .NET applications pick up -- when there is only 32MB of available RAM on a system.

2 Comments

  • This isn't always true. Is it? If I have an application that allocated several medium sized (2KB to 10KB) sized objects for some time causing over 100MB of heap memory to be allocated,' and then released them all and went into a suspended state because there was no more "work to be done, I would expect GC to release most of the managed heap back to the system. I would be interested in knowing what kind of triggers can cause unused memory from managed heap to be returned to the OS.

  • While the GC "might" release it back to the OS, it appears that it only does this in certain situations, like a very limited amount of free memory available to the OS, or minimizing an app. There may very well be other triggers, but it appears you can't really expect the GC to just un-reserve its memory for no reason.

Comments have been disabled for this content.