10101010101001

0101010101001

Archive for the ‘AppDomain’ Category

AppDomain.Unload Garbage Collection

with 2 comments

It all started while I was investigating memory usage in a .net 2.0 system. The system was organized into independent components that were loaded into Application Domains.

The components performed their jobs in the isolated environment an AppDomain provides and, when their job finished, they were unloaded using AppDomain.Unload.

The problem was that memory didn’t seem to be recollected when I was doing AppDomain.Unload so I turned to read again sections from Jeffrey Richter’s, CLR via C# 3rd edition, since that was the book from which I’ve learned about Application Domains and Garbage Collection. It stated clearly “The CLR forces a garbage collection to occur, reclaiming the memory used by any objects that were created by the now unloaded AppDomain. The Finalize methods for these objects are called, giving the objects a chance to clean themselves up properly.”

After some mail exchange with Jeffrey, which you can read, along with an example here, he suggested:

A better test would be to look at some object addresses in the debugger and see if compaction actually occurs. If it does (and I suspect it does), then the collection count is just not being updated correctly.

To keep it short I had a small program that did this:

1) Create and application domain,

2) Create some object instances inside so It has some allocated memory.

2) Call AppDomain.Unload

3) Perform an explicit GC.Collect() call.

I took Visual Studio and loaded Son of Strike into it and it revealed this:

Before AppDomain.Unload:

!EEHeap -gc
Number of GC Heaps: 1
generation 0 starts at 0x0180b1f0
generation 1 starts at 0x017d100c
generation 2 starts at 0x017d1000
ephemeral segment allocation context: none
segment    begin allocated     size
017d0000 017d1000  01811ff4 0x00040ff4(266228)
Large object heap starts at 0x027d1000
segment    begin allocated     size
027d0000 027d1000  02f75470 0x007a4470(8012912)
Total Size  0x7e5464(8279140)
——————————
GC Heap Size  0x7e5464(8279140)

After AppDomain.Unload (same addresses, no heap compaction was done)

!EEHeap -gc
Number of GC Heaps: 1
generation 0 starts at 0x0180b1f0
generation 1 starts at 0x017d100c
generation 2 starts at 0x017d1000
ephemeral segment allocation context: none
segment    begin allocated     size
017d0000 017d1000  01811ff4 0x00040ff4(266228)
Large object heap starts at 0x027d1000
segment    begin allocated     size
027d0000 027d1000  02f75470 0x007a4470(8012912)
Total Size  0x7e5464(8279140)
——————————
GC Heap Size  0x7e5464(8279140)

After GC.Collect(), addresses differ indicating heap compaction was done.

!EEHeap -gc
Number of GC Heaps: 1
generation 0 starts at 0x01811234
generation 1 starts at 0x0180b1f0
generation 2 starts at 0x017d1000
ephemeral segment allocation context: none
segment    begin allocated     size
017d0000 017d1000  01811ff4 0x00040ff4(266228)
Large object heap starts at 0x027d1000
segment    begin allocated     size
027d0000 027d1000  027d3240 0x00002240(8768)
Total Size   0x43234(274996)
——————————
GC Heap Size   0x43234(274996)

So to conclusion is that heap compaction is not done and the only thing you can really be sure during an AppDomain unload is that objects will get to be marked as unreachable.

Memory for those objects will be reclaimed whenever the next garbage collection happens, so, in this case it’s not a good idea to call for GC.Collect() yourself.

Advertisements

Written by Liviu Trifoi

May 21, 2010 at 5:24 pm

Posted in .NET, AppDomain, C#, debugging

Tagged with