我正在尝试理解堆碎片是如何工作的。下面的输出告诉我什么?
这个堆是否过于碎片化了?
我有243010个“自由对象”,总共有53304764个字节。堆中的“空闲对象”空间是否曾经包含对象,但现在已被垃圾收集?
如何强制清理碎片化的堆?
!dumpheap -type Free -stat
total 243233 objects
Statistics:
MT Count TotalSize Class Name
0017d8b0 243010 53304764 Free发布于 2011-07-02 05:43:19
这取决于堆是如何组织的。您应该查看Gen 0,1,2中分配了多少内存,以及与总已用内存相比,Gen 0,1,2有多少空闲内存。如果你使用了500MB的托管堆,但是50MB是空闲的,那么你就做得很好了。如果您执行内存密集型操作,如创建许多WPF控件并释放它们,那么在短时间内您需要更多的内存,但是一旦您分配了内存,.NET就不会将内存交还给操作系统。GC试图识别分配模式,并倾向于保持较高的内存占用,尽管您当前的堆大小太大,直到您的机器的物理内存不足。
我发现在.NET 3.5上使用psscor2要容易得多,它有一些很酷的命令,比如ListNearObj,在这些命令中,你可以发现哪些对象在你的内存漏洞周围(固定的对象?)。使用psscor2中的命令,您有更好的机会了解堆中到底发生了什么。大多数命令在.NET 4的SOS.dll中也可用。
回答你最初的问题:是的,空闲对象是托管堆上的空隙,可以只是在GC段上最后分配的对象之后的空闲内存块。或者,如果您这样做了!DumpHeap使用GC段的起始地址,您将看到在该托管堆段中分配的对象以及您的自由对象,这些对象是GC收集的对象。
这种内存漏洞通常发生在Gen2中。自由对象之前和之后的对象地址确实会告诉您洞周围有哪些可能被钉住的对象。由此,您应该能够确定您的分配历史记录,并在需要时对其进行优化。您可以使用以下命令查找GC堆的地址
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.在这里,您可以看到02aa1000和10061000处的堆。使用!DumpHeap 02aa1000 03836a30,您可以转储GC堆段。
!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
....在那里你可以找到你的空闲内存块,它是一个已经是GCed的对象。您可以转储周围的对象(输出按地址排序),以找出它们是否被固定或具有其他不寻常的属性。
https://stackoverflow.com/questions/6465375
复制相似问题