2015-12-20 17 views
10

Tôi đã xem xét tác động bộ nhớ của truy vấn LINQ đơn giản và nhận thấy rằng truy vấn LINQ đã tạo thêm 2 đối tượng thuộc loại Enumerable+WhereListIterator<Int32>Func<Int32, Boolean>.Tại sao một GC sau một truy vấn LINQ miễn phí các WhereListIterator nhưng không phải là Func đại diện cho điều kiện?

Mã được sử dụng là:

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(); 
} 

Tại ảnh chụp sau khi foreach loop Tôi nhận thấy rằng đối tượng Enumerable+WhereListIterator<Int32> là thu gom rác nhưng Func<Int32, Boolean> vẫn còn trong bộ nhớ.

Tại sao điều này vẫn được lưu giữ? Tại thời điểm đó trong thời gian (tại câu hỏi Console.Read) Tôi không nghĩ rằng bất cứ điều gì vẫn còn tham chiếu nó và một GC đã bị buộc bởi profiler (đó là lý do tại sao các iterator được thu thập).

Lưu ý: thu thập thêm ảnh chụp nhanh không làm thay đổi số lượng đối tượng được giải phóng, vì vậy không phải là vấn đề của Func được đánh dấu để thu thập cho lần chạy tiếp theo.

+0

Nhận xét về việc mở lại câu hỏi: mặc dù câu hỏi được liên kết chắc chắn có liên quan, câu hỏi này yêu cầu về một trường hợp cụ thể và cung cấp bản trình diễn để minh họa những gì đang diễn ra. – dasblinkenlight

+0

@dasblinkenlight đủ công bằng, chúng ta hãy giữ nó mở sau đó. –

Trả lời

11

Lý do lambda không GC-ed là cấu trúc của lambda bản thân:

item => item > 5000 && item < 7000 

lambda này không chụp bất cứ điều gì, có nghĩa là nó có thể được biên dịch một lần, và tái sử dụng mãi mãi. C# phát hiện ra điều này, và tận dụng lợi thế của lambdas như thế bằng cách lưu trữ chúng tĩnh để cải thiện hiệu suất.

Nếu lambda của bạn đã chụp một biến từ ngữ cảnh của nó, nó sẽ là rác được thu thập khi nó không còn cần thiết nữa.

Xem this answer để biết thêm thông tin về tuổi thọ lambda trong .NET.

+0

Hoàn hảo, điều đó và các câu trả lời được liên kết giải thích mọi thứ. –

Các vấn đề liên quan