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
- OOM Exception Thrown
- Array Size: 134,217,728
End Loop: memory 550,408,192
Start Loop: memory 550,731,776
- OOM Exception Thrown
- Array Size: 134,217,728
End Loop: memory 551,682,048
Start Loop: memory 551,813,120
- OOM Exception Thrown
- Array Size: 134,217,728
End Loop: memory 551,772,160
Start Loop: memory 551,903,232
- OOM Exception Thrown
- Array Size: 67,108,864
End Loop: memory 282,869,760
Start Loop: memory 283,004,928
- OOM Exception Thrown
- Array Size: 67,108,864
End Loop: memory 282,910,720
GC.Collect manually triggered
Start Loop: memory 14,245,888
- OOM Exception Thrown
- Array Size: 67,108,864
End Loop: memory 283,344,896