2011-06-24 69 views
9

Tôi đang cố gắng hiểu cách hoạt động của phân đoạn heap. Đầu ra sau cho tôi biết điều gì?phân mảnh heap được quản lý

Heap này có bị phân mảnh quá mức không?

Tôi có 243010 "đối tượng miễn phí" với tổng số 53304764 byte. Có phải những không gian "đối tượng tự do" đó trong heap đã từng chứa đối tượng nhưng bây giờ đã thu thập được garabage chưa?

Làm thế nào tôi có thể buộc một đống phân mảnh để dọn dẹp?

!dumpheap -type Free -stat 
total 243233 objects 
Statistics: 
     MT Count TotalSize Class Name 
0017d8b0 243010  53304764  Free 

Trả lời

6

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.

+0

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

+0

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 đủ. –

0

Bạn có 50MB bộ nhớ RAM làm dung lượng trống. Điều này không tốt.

Có .NET phân bổ khối 16MB từ quy trình, chúng tôi có vấn đề phân mảnh thực sự. Có rất nhiều lý do để phân mảnh xảy ra trong .NET.

Có giao diện herehere. Trong trường hợp của bạn, nó có thể là một ghim. Khi 53304764/243010 tạo ra 219,35 byte cho mỗi đối tượng - thấp hơn nhiều so với đối tượng LOH.

+0

Ok, tôi có 50 MB dung lượng miễn phí, nhưng tính năng * Count * cho tôi biết điều gì? Tôi biết tôi thường xuyên tạo nhiều đối tượng nhỏ (ví dụ: tạo ra một mạng lưới ~ 20000 điều khiển WPF sau mỗi 10 giây, nhưng các điều khiển cũ trở nên không được quan tâm, không bị rò rỉ bộ nhớ ở đây). Có thể giải thích nó hoặc nên ghim các đối tượng có nhiều khả năng hơn. – bitbonk

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