I was looking at the memory impact of a simple LINQ query and noticed that the LINQ query created 2 extra objects of types Enumerable+WhereListIterator<Int32>
and Func<Int32, Boolean>
.
The code used is this:
static void Main(string[] args)
{
// Setting baseline snapshot
var list1 = new List<int> { 4862, 6541, 7841 };
var list2 = new List<int>(list1.Count);
var list3 = new List<int>(list1.Count);
// First snapshot: LINQ usage
list2.AddRange(list1.Where(item => item > 5000 && item < 7000));
// Second snapshot: foreach-loop
foreach (var item in list1)
{
if (item > 5000 && item < 7000)
{
list3.Add(item);
}
}
// End gather
Console.Read();
}
At the snapshot after the foreach
loop I notice that the Enumerable+WhereListIterator<Int32>
object is garbage collected but the Func<Int32, Boolean>
is still in memory.
Why is this still kept around? At that point in time (at the Console.Read
statement) I don't think anything is still referencing it and a GC has been forced by the profiler (which is why the iterator is collected).
Note: collecting additional snapshots does not alter how many objects are freed so it's not a matter of the Func
being marked for collection for the next run.