I'm troubleshooting an OutOfMemory exception in my .NET 2.0 Windows Service application. To understand the issue better I began by writing a simple .NET WinForm test app that generates an OOM Exception by building an ArrayList until an OOM Exception is thrown. The exception is caught and logged and I can click on a form button to run the OOME again. The strange thing I found was on the 4th run, the amount of memory consumed before the next OOME was roughly half. The results listed below are consistent every time I run this. Eyeballing TaskManager also confirms the behavior. Unfortunately, Perfmon froze up when trying to get better stats. Can someone explain why the memory limit is lowered after 3 runs? My understanding of GC is fairly shallow. You can also see I ran a GC.Collect() after a few more runs but it didn't help with the lowered limit.
UPDATE: I also found a big difference using a const string vs a new object for each arraylist item. Code is simply:
const string TEST_TEXT = "xxxxxxxxxx";
ArrayList list = new ArrayList();
while (true)
{
list.Add(TEST_TEXT);
}
Start Loop: memory 10,350,592
End Loop: memory 550,408,192
Start Loop: memory 550,731,776
End Loop: memory 551,682,048
Start Loop: memory 551,813,120
End Loop: memory 551,772,160
Start Loop: memory 551,903,232
End Loop: memory 282,869,760
Start Loop: memory 283,004,928
End Loop: memory 282,910,720
GC.Collect manually triggered
Start Loop: memory 14,245,888
End Loop: memory 283,344,896
Here are several points which, taken together, hopefully will give you enough information to answer your question:
Since you are building arrays, I assume that you are building one big array for each run. If this is the case it will be stored in the Large Object Heap (as it will be > 85000 bytes). LOH is not compacted like the generational heap, so the drop in size you're seeing is probably due to heap fragmentation.
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