I'm having an issue freeing memory from a List<>
when items are removed. It's the strangest thing, memory is only released from the application when a second set of items are added and removed from the List<>
. I was able to illustrate the issue using this simple console application:
C# .Net4.0
namespace MemoryTestApp
{
class Program
{
static int numObjects = 1000;
static int objectSize = 10000;
class Obj
{
byte[] buffer = new byte[objectSize];
public Obj()
{
buffer[0] = 1;
buffer[buffer.Length - 1] = 1;
}
}
private static List<Obj> list = new List<Obj>();
static void Main(string[] args)
{
while(true)
{
Console.WriteLine("Press Enter to add {0} objects to list...", numObjects);
Console.ReadLine();
//add to list of objects
for (int i = 0; i < numObjects; i++)
{
list.Add(new Obj());
}
//double num objects for next round so we can see which block of memory is released
numObjects = numObjects * 2;
Console.WriteLine("Press Enter to remove objects from list...");
Console.ReadLine();
foreach (Obj _obj in list.ToList())
{
list.Remove(_obj);
}
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
Console.WriteLine("Press Enter to trim excess from list...");
Console.ReadLine();
list.TrimExcess();
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
}
}
}
}
Basically, the block of memory used by items added in round N
is only released after new items are added then removed in round N+1
(approximately, this is more easily visible in rounds > 3). I tested the issue using the resolution here and here however the behavior didn't appear to change at all.
This is probably still related to GC behavior but even given the references above I can't make it work as I expect it should. So where is the fault in my code, or my expectations? I greatly appreciate any assistance.