Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does a GC after a LINQ query free the WhereListIterator but not the Func representing the condition?

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.

like image 879
Jeroen Vannevel Avatar asked Dec 20 '15 01:12

Jeroen Vannevel


1 Answers

The reason the lambda is not GC-ed is the structure of the lambda itself:

item => item > 5000 && item < 7000

This lambda does not capture anything, meaning that it can be compiled once, and reused forever. C# discovers this, and takes advantage of lambdas like that by caching them statically to improve performance.

Had your lambda captured a variable from its context, it would have been garbage collected when it is no longer needed.

See this answer for more information on lambda lifetime in .NET.

like image 198
Sergey Kalinichenko Avatar answered Oct 22 '22 02:10

Sergey Kalinichenko