在检查故障转储文件以查找客户端报告的内存不足异常时,!DumpHeap -stat
的结果显示,575MB的内存被45000个"Free"类型的对象占用,我认为由于大小的原因,其中大部分必须位于Gen 2中。
我首先查找问题的地方是大对象堆(LOH)和固定对象。包含可用空间的大对象堆只有70MB,所以这不是问题所在,运行!gchandles
显示:
GC Handle Statistics:
Strong Handles: 155
Pinned Handles: 265
Async Pinned Handles: 8
Ref Count Handles: 163
Weak Long Handles: 0
Weak Short Handles: 0
Other Handles: 0
与自由对象的数量(45000)相比,这是非常少量的句柄(大约600)。对我来说,这排除了由钉扎引起的空闲块。
我还研究了空闲块本身,看看它们是否有一致的大小,但经过检查,大小变化很大,从不足5MB到只有12字节左右
任何帮助都将不胜感激!我不知所措,因为有碎片,但没有迹象表明这是由我知道要看的两个地方引起的,那就是大对象堆(LOH)和固定句柄。
自由对象在哪一代
由于的大小,我认为必须驻留在第2代
大小与世代无关。要找出空闲块所在的生成,您可以按照以下步骤操作:
从!dumpheap -stat -type Free
得到方法表:
0:003> !dumpheap -stat -type Free
total 7 objects
Statistics:
MT Count TotalSize Class Name
00723538 7 100 Free
Total 7 objects
从!eeheap -gc
中,获取各代的起始地址。
0:003> !eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x026a1018
generation 1 starts at 0x026a100c
generation 2 starts at 0x026a1000
ephemeral segment allocation context: none
segment begin allocated size
026a0000 026a1000 02731ff4 0x00090ff4(593908)
Large object heap starts at 0x036a1000
segment begin allocated size
036a0000 036a1000 036a3250 0x00002250(8784)
Total Size 0x93244(602692)
------------------------------
GC Heap Size 0x93244(602692)
然后通过传递起始和结束地址(例如,此处为第2代),仅转储特定一代的空闲对象:
0:003> !dumpheap -mt 00723538 0x026a1000 0x026a100c
Address MT Size
026a1000 00723538 12 Free
026a100c 00723538 12 Free
total 2 objects
Statistics:
MT Count TotalSize Class Name
00723538 2 24 Free
Total 2 objects
因此,在我的简单例子中,第2代中有2个自由对象。
固定手柄
600个固定对象不应导致45.000个可用内存块。根据我的经验,600个固定把手还是很多的。但首先,检查空闲内存块所在的代。