我在服务器类Windows 2012 R2机器上遇到麻烦,偶尔会将其托管的.net堆增加到10GB以上(通常应该是1-2 GB)。我在Gen2集合之后对此框进行了内存转储,以尝试查找在堆上分配的对象。
使用WinDbg / SOS
!dumpheap -stat
生成一个对象列表,其中最大的是〜150mb的内存,并且很快就会落后。将此输出拉入excel并添加TotalSize,我只获得1.5 GB的对象(符合我的预期)。
MT Count TotalSize Class Name
00007ffb1ab87a70 1 24 System.Collections.Generic.GenericEqualityComparer`1[[System.UInt64, mscorlib]]
...
00007ffabc178e40 218274 36670032 Ten.RunBar
00007ffabbd172f8 1048576 41943040 Ten.DisruptorTaskTuple
00007ffb1a0502c0 442990 71357200 System.Object[]
00007ffabc1bbce0 676327 97391088 Ten.BalTuple
00007ffabbd5eea8 2342912 149946368 Ten.Run.TaskAction
0000001bf119dc70 1072558 787427166 Free
MANUALLY CALCULATED TOTAL: 1589298584
我的第一个想法是存在一些非托管内存泄漏,所以我用
检查了堆!EEHeap -gc
表明GC堆大小本身实际上是10GB
Number of GC Heaps: 1
generation 0 starts at 0x0000001e10623cb0
generation 1 starts at 0x0000001e10485bb0
generation 2 starts at 0x0000001b80001000
ephemeral segment allocation context: none
segment begin allocated size
0000001b80000000 0000001b80001000 0000001b90000000 0xffff000(268431360)
0000001b98000000 0000001b98001000 0000001ba8000000 0xffff000(268431360)
...
0000001e04ee0000 0000001e04ee1000 0000001e109c2cc0 0xbae1cc0(195960000)
Large object heap starts at 0x0000001b90001000
segment begin allocated size
0000001b90000000 0000001b90001000 0000001b9356cbc8 0x356bbc8(56015816)
Total Size: Size: 0x25f028618 (10183935512) bytes.
------------------------------
GC Heap Size: Size: 0x25f028618 (10183935512) bytes.
我已确认内存全部位于第二代堆(性能计数器)中,但我不确定从何处查找缺少的8.5 GB托管对象。
有哪些其他想法/ WinDbg / SOS命令可以帮助找到这些?
答案 0 :(得分:4)
!dumpheap
报告的大小是类型本身的大小,而不是实例的实际大小。
您可以使用!objsize
列出实例的大小。但是,由于多个实例可能共享引用,因此对!objsize
的输出求和的相同对象通常也会创建不正确的结果。
确定托管堆大小的最佳方法是查看!dumpheap
和!eeheap
报告的总计。