摘要 :

NetExt中有两个比较常用的命令可以用来分析heap上面的对象. 一个是!wheap, 另外一个是!windex.

!wheap 这个命令可以用于打印出heap structure信息. heap 上 object汇总后的信息. 这个命令也可以按照一些条件过滤出objects, 不过执行速度比较慢. 在这一点上, 更推荐!windex.
!windex是一个非常常用的命令. 这个命令可以用来查找heap上面实现某个interface, 继承某个abstract class 或者class的对象. 这个命令执行之后, 也会缓存做过index后的对象, 可以加快类似命令的之行速度. 同时也有非常酷炫的功能, 可以批量的从同一类型的object中显示出个别字段.

!wheap 这个命令可以用于打印出heap structure信息. 以及heap object的汇总后的信息.  加上参数 –detailsonly, 正如他的名字一样, 可以打印出详细的信息.

它可以显示出的Heap的数量, 由于这个CLR RUTIME使用的GC Mode是Server Mode (1). 那么Heap的数量会根据Processor的数量有所不同. 这里能够看到Heap的数量是2个.

关于GC 类型的区别, 可以参考下面的链接

从输出结果可以看出来每个Managed Heap都有自己的一段地址. 如果Heap的size比较大, 还会包含多个Segment. 每个Segment的最大值都是固定的. 最大值值由很多因素决定. 不同的环境和配置时, 这个值会不一样. 当一个Segment将要分配满的时候, 会创建出一个新的Segment. 这个Segment 会缓慢增长, 直到长满为止.

这个命令也会提示GC Heap 上不同Generation代上的object的数量. 比较特别的是 Generation 3. 我们所认识的Generation 3. 


0:000> !wheap -detailsonly
Heaps: 2           <-- heap 的数量 --> 
Server Mode: 1   <-- GC Mode, 1表示是Server Mode --> 
Heap [0]:                <-- 第一个Heap -->
    Allocated: 0000000155a56fe8
    Card Table: 00000000027ea6b0
    Ephemeral Heap Segment: 0000000155660000
    Finalization Fill Pointers: 000000c28007cd40
    Heap Address: 0000000000e1e790
    Lowest Address: 0000000155660000
    Highest Address: 00000001f5660000
    Generation Addresses:
        [0]:AllocStart(0000000155793728),AllocCxtLimit(0000000000000000),AllocCtxPtr(0000000000000000),StartSeg(0000000155660000)
        [1]:AllocStart(0000000155660080),AllocCxtLimit(0000000000000000),AllocCtxPtr(0000000000000000),StartSeg(0000000155660000)
        [2]:AllocStart(0000000155660068),AllocCxtLimit(0000000000000000),AllocCtxPtr(0000000000000000),StartSeg(0000000155660000)
        [3]:AllocStart(00000001d5660068),AllocCxtLimit(0000000000000000),AllocCtxPtr(0000000000000000),StartSeg(00000001d5660000)

Segments:
Segment: 0000000155660000 Start: 0000000155660068 End: 0000000155981340 HiMark: 0000000155a56fe8 Committed: 0000000155a61000 Reserved: 0000000195660000 Next: 0000000000000000  <-- 第一个Segment, 由于有第二个Segment已经创建出来, 可以猜测这个Segment已经快分配完. 用End的地址减去Start的地址能够算出一个Segment的大小. 这里是64MB. -->
Segment: 00000001d5660000 Start: 00000001d5660068 End: 00000001d569bf10 HiMark: 00000001d569bf10 Committed: 00000001d56a1000 Reserved: 00000001e5660000 Next: 0000000000000000
Heap [1]:
    Allocated: 0000000195907af8
    Card Table: 00000000027ea6b0
    Ephemeral Heap Segment: 0000000195660000
    Finalization Fill Pointers: 000000c28007cd40
    Heap Address: 0000000000e20db0
    Lowest Address: 0000000155660000
    Highest Address: 00000001f5660000
    Generation Addresses:
        [0]:AllocStart(000000019573e270),AllocCxtLimit(0000000000000000),AllocCtxPtr(0000000000000000),StartSeg(0000000195660000)
        [1]:AllocStart(0000000195660080),AllocCxtLimit(0000000000000000),AllocCtxPtr(0000000000000000),StartSeg(0000000195660000)
        [2]:AllocStart(0000000195660068),AllocCxtLimit(0000000000000000),AllocCtxPtr(0000000000000000),StartSeg(0000000195660000)
        [3]:AllocStart(00000001e5660068),AllocCxtLimit(0000000000000000),AllocCtxPtr(0000000000000000),StartSeg(00000001e5660000)

Segments:
Segment: 0000000195660000 Start: 0000000195660068 End: 0000000195907af8 HiMark: 0000000195907af8 Committed: 0000000195911000 Reserved: 00000001d5660000 Next: 0000000000000000
Segment: 00000001e5660000 Start: 00000001e5660068 End: 00000001e5660080 HiMark: 00000001e5660080 Committed: 00000001e5661000 Reserved: 00000001f5660000 Next: 0000000000000000

Heap Areas:
Area [0000000155660068]: 0000000155660068-0000000155660080 (        24) Heap: 0 Generation: 2 Large: 0  <-- 表示 24个对象处于Generation 2 -->
Area [0000000155660080]: 0000000155660080-0000000155793728 (   1259176) Heap: 0 Generation: 1 Large: 0
Area [0000000155793728]: 0000000155793728-0000000155a61000 (   2939096) Heap: 0 Generation: 0 Large: 0
Area [0000000195660068]: 0000000195660068-0000000195660080 (        24) Heap: 1 Generation: 2 Large: 0
Area [0000000195660080]: 0000000195660080-000000019573e270 (    909808) Heap: 1 Generation: 1 Large: 0
Area [000000019573e270]: 000000019573e270-0000000195911000 (   1912208) Heap: 1 Generation: 0 Large: 0
Area [00000001d5660068]: 00000001d5660068-00000001d569bf10 (    245416) Heap: 0 Generation: 3 Large: 1  <-- 表示 245416个对象处于Generation 3, 即Large Object Heap -->
Area [00000001e5660068]: 00000001e5660068-00000001e5660080 (        24) Heap: 1 Generation: 3 Large: 1
0000000155660068 0000000000e111d0       24   0 2 Free
0000000155660080 0000000000e111d0       24   0 1 Free
0000000155660098 0000000000e111d0       24   0 1 Free
00000001556600b0 000007fef0b96cb8      160   0 1 System.Exception
0000000155660150 000007fef0b96f10      160   0 1 System.OutOfMemoryException
00000001556601f0 000007fef0b96f98      160   0 1 System.StackOverflowException
0000000155660290 000007fef0b97020      160   0 1 System.ExecutionEngineException
0000000155660330 000007fef0b970a8      160   0 1 System.Threading.ThreadAbortException
00000001556603d0 000007fef0b970a8      160   0 1 System.Threading.ThreadAbortException

.....
0000000195747da0 000007fee67a1e60       32   1 0 System.Xml.Schema.XmlSchemaObjectTable+ValuesCollection
0000000195747dc0 000007fee67a1f28       56   1 0 System.Xml.Schema.XmlSchemaObjectTable+XSOEnumerator
0000000195747df8 000007fef0b9c768       36   1 0 System.Int32[]
0000000195747e20 000007fee67a2048       96   1 0 System.Collections.Generic.Dictionary`2+Entry[[System.Xml.XmlQualifiedName, System.Xml],[System.Xml.Schema.XmlSchemaObject, System.Xml]][]
0000000195747e80 000007fee679fd20       88   1 0 System.Xml.Schema.XmlSchemaObjectTable+XmlSchemaObjectEntry[]
0000000195747ed8 000007fee67a1e60       32   1 0 System.Xml.Schema.XmlSchemaObjectTable+ValuesCollection
00000001d5660068 0000000000e111d0       24   0 3 Free
00000001d5660080 000007fef0b9adf8     8192   0 3 System.Object[]
.....

This output was throttled. Only the first 500 objects of each heap range has been shown.
Use -nothrottle to list all objects or any limiting parameter (-type for example)
View Code

- detailsonly 的目的是打印出来Heap的structure的信息. Object仅仅打印前500个. 如果要打印出的Heap上所有的对象, 则要使用参数 –nothrottle, 不过这一命令的运行时间会略长.

相关文章: