Nó phụ thuộc vào cách tổ chức heap của bạn. Bạn nên có một cái nhìn bao nhiêu bộ nhớ trong Gen 0,1,2 được phân bổ và bao nhiêu bộ nhớ miễn phí bạn có có so với tổng số bộ nhớ được sử dụng. Nếu bạn có 500 MB quản lý heap được sử dụng nhưng và 50 MB là miễn phí thì bạn đang làm khá tốt. Nếu bạn thực hiện các thao tác tốn nhiều bộ nhớ như tạo nhiều điều khiển WPF và giải phóng chúng, bạn cần nhiều bộ nhớ hơn trong một thời gian ngắn nhưng .NET không cung cấp bộ nhớ cho hệ điều hành khi bạn đã cấp phát. GC cố gắng để nhận ra các mẫu phân bổ và có xu hướng giữ chân bộ nhớ của bạn cao mặc dù kích thước heap hiện tại của bạn quá lớn cho đến khi máy của bạn sắp hết bộ nhớ vật lý.
Tôi thấy dễ dàng hơn khi sử dụng psscor2 cho .NET 3.5 có một số lệnh thú vị như ListNearObj nơi bạn có thể tìm ra đối tượng nào nằm xung quanh lỗ bộ nhớ của bạn (đối tượng được ghim?). Với các lệnh từ psscor2 bạn có nhiều cơ hội tốt hơn để tìm hiểu những gì đang thực sự xảy ra trong đống của bạn. Hầu hết các lệnh cũng có sẵn trong SOS.dll trong .NET 4.
Để trả lời câu hỏi ban đầu: Có đối tượng miễn phí là khoảng trống trên heap được quản lý, đơn giản là khối bộ nhớ miễn phí sau đối tượng được phân bổ cuối cùng của bạn trên phân đoạn GC. DumpHeap với địa chỉ bắt đầu của một phân đoạn GC bạn thấy các đối tượng được phân bổ trong phân đoạn heap được quản lý cùng với các đối tượng miễn phí của bạn là các đối tượng được thu thập GC.
Lỗ bộ nhớ này thường xảy ra trong Gen2. Các đối tượng địa chỉ trước và sau khi đối tượng miễn phí cho bạn biết những gì có khả năng pinned đối tượng là xung quanh lỗ của bạn. Từ đó bạn sẽ có thể xác định lịch sử phân bổ của bạn và tối ưu hóa nó nếu bạn cần. Bạn có thể tìm ra địa chỉ của các Heaps GC với
0:021> !EEHeap -gc
Number of GC Heaps: 1
generation 0 starts at 0x101da9cc
generation 1 starts at 0x10061000
generation 2 starts at 0x02aa1000
ephemeral segment allocation context: none
segment begin allocated size
02aa0000 02aa1000** 03836a30 0xd95a30(14244400)
10060000 10061000** 103b8ff4 0x357ff4(3506164)
Large object heap starts at 0x03aa1000
segment begin allocated size
03aa0000 03aa1000 03b096f8 0x686f8(427768)
Total Size: Size: 0x115611c (18178332) bytes.
------------------------------
GC Heap Size: Size: 0x115611c (18178332) bytes.
Ở đó bạn thấy rằng bạn có đống tại 02aa1000 và 10061000. Với! DumpHeap 02aa1000 03836a30 bạn có thể đổ phân khúc GC Heap.
!DumpHeap 02aa1000 03836a30
Address MT Size
...
037b7b88 5b408350 56
037b7bc0 60876d60 32
037b7be0 5b40838c 20
037b7bf4 5b408350 56
037b7c2c 5b408728 20
037b7c40 5fe4506c 16
037b7c50 60876d60 32
037b7c70 5b408728 20
037b7c84 5fe4506c 16
037b7c94 00135de8 519112 Free
0383685c 5b408728 20
03836870 5fe4506c 16
03836880 608c55b4 96
....
Ở đó bạn tìm thấy các khối bộ nhớ miễn phí là đối tượng đã được GC. Bạn có thể đổ các đối tượng xung quanh (đầu ra được sắp xếp địa chỉ khôn ngoan) để tìm hiểu xem chúng được ghim hay có các thuộc tính bất thường khác.
Nguồn
2011-07-01 21:43:19
Có thể phân mảnh heap xảy ra (và cuối cùng gây ra một OutOfMemoryException) ** mà không có ** đối tượng được ghim? Tôi hiểu GC là người dọn dẹp một đống phân mảnh. Nếu không có các đối tượng được ghim, liệu GC vẫn không thể dọn sạch đống thời gian cho một yêu cầu bộ nhớ mới? Điều gì ngoại trừ các đối tượng được ghim có thể gây ra một đống phân mảnh mà không thể dọn dẹp (theo thời gian) khi phân bổ mới cần được thực hiện? – bitbonk
Nếu tỷ lệ phân bổ rất cao, bạn có thể hết bộ nhớ. Các clr đã thực sự là một giấc ngủ (50) được xây dựng trong để điều tiết các yêu cầu phân bổ của bạn nếu bạn đang phân bổ trong một vòng lặp chặt chẽ để cung cấp cho GC một cơ hội để làm sạch nhưng nó có thể là không đủ. –