【问题标题】:search objects with size larger then a threshold搜索大小大于阈值的对象
【发布时间】:2016-10-19 21:17:11
【问题描述】:

其中一个类在 .NET 堆中存在许多对象,这是通过以下 sos 命令发现的。

!dumpheap -stat  -type MyClass
Statistics:
              MT    Count    TotalSize    Class Name
00007ff8e6253494     1700     164123  MyNameSpace.MyClass

我需要找到那些 ObjSize 大于 5 MB 的对象的实例。我知道我可以使用以下方法列出所有 1700 个 MyClass 实例中的 objsize

.foreach (res {!DumpHeap -short -MT 00007ff8e6253494 }) {.if ( (!objsize res) > 41943040) {.echo res; !objsize res}}

使用上面的脚本,尽管有大于 5MB 的对象实例,但我没有得到任何结果。我认为问题可能是 objsize 的输出如下

20288 (0x4f40) bytes

它是一个字符串,很难与任何阈值进行比较。我怎样才能让这个脚本只列出 objsize 大于 5MB 的对象?

【问题讨论】:

  • 我已经删除了我的答案,因为我不小心发布了一个相当于 !objsize 的解决方案。

标签: windbg sos sosex


【解决方案1】:

在 WinDbg 中创建复杂的脚本很容易出错。在这种情况下,我切换到PyKd,这是一个使用 Python 的 WinDbg 扩展。

在下文中,我将仅介绍您拼图中缺少的部分,即不起作用的部分:

.if ( (!objsize res) > 41943040) {.echo res; !objsize res}

这是我的出发点:

0:009> !dumpheap -min 2000
         Address               MT     Size
00000087c6041fe8 000007f81ea5f058    10158     
00000087d6021018 000007f81ea3f1b8     8736     
00000087d6023658 000007f81ea3f1b8     8192     
00000087d6025658 000007f81ea3f1b8    16352     
00000087d6029638 000007f81ea3f1b8    32672  

你可以写一个这样的脚本(没有错误处理!)

from pykd import *
import re
import sys
objsizeStr = dbgCommand("!objsize "+sys.argv[1])
number = re.search("= (.*)\(0x", objsizeStr)
size = int(number.group(1))
if size > 10000:
    print sys.argv[1], size

并在你的循环中使用它:

0:009> .foreach (res {!dumpheap -short -min 2000}) { !py c:\tmp\size.py ${res}}
00000087c6041fe8 10160
00000087d6021018 37248
00000087d6023658 27360
00000087d6025658 54488
00000087d6029638 53680

注意!objsize 的大小与!dumpheap 的大小有何不同。仅用于交叉检查:

0:009> !objsize 00000087d6023658
sizeof(00000087d6023658) = 27360 (0x6ae0) bytes (System.Object[])

另请参阅this answer,了解如何使用expr() 改进脚本,以便您可以传递表达式等。我这样做的方式现在以十进制输出大小,但这并不明确。也许您想输出一个0n 前缀以使其清楚。

【讨论】:

  • 好点。我将包括它,但是,我在这里要问的是如何将包含十进制、十六进制和单位(字节)大小的 objsize 的返回值与阈值进行比较。
【解决方案2】:

正如史蒂夫评论的那样!dumpeap 需要一个 min 和 max 参数,并且应该可以在本地执行它

0:004> !DumpHeap -type System.String -stat

Statistics:
      MT    Count    TotalSize Class Name
6588199c        1           12 System.Collectionsxxxxx
65454aec        1           48 System.Collectionsxxxxx
65881aa8        1           60 System.Collectionsxxxxx
6587e388       17          596 System.String[]
6587d834      168         5300 System.String
Total 188 objects

0:004> !DumpHeap -type System.String -stat -min 0n64 -max 0n100

Statistics:
      MT    Count    TotalSize Class Name
6587e388        3          212 System.String[]
6587d834        9          684 System.String
Total 12 objects

0:004> !DumpHeap -type System.String -min 0n64 -max 0n100

 Address       MT     Size
01781280 6587d834       76     
01781354 6587d834       78     
01781478 6587e388       84     
017816d8 6587d834       64     
01781998 6587d834       78     
017819e8 6587d834       70     
01781a30 6587d834       82     
01782974 6587d834       78     
01782a6c 6587d834       90     
01782c7c 6587d834       68     
01783720 6587e388       64     
01783760 6587e388       64     

Statistics:
      MT    Count    TotalSize Class Name
6587e388        3          212 System.String[]
6587d834        9          684 System.String
Total 12 objects

操纵最大值,最小值我们可以微调到一两个对象
一个例子,我们在上侧有 1 个额外的对象,在下侧有 2 个额外的对象
来自此之前的输出(15 个对象对 12 个对象)

0:004> !DumpHeap -type System.String -min 0n62 -max 0n106

 Address       MT     Size
01781280 6587d834       76     
01781354 6587d834       78     
017813e8 6587d834       62     
01781478 6587e388       84     
017816d8 6587d834       64     
01781898 6587d834      106     
01781998 6587d834       78     
017819e8 6587d834       70     
01781a30 6587d834       82     
01782974 6587d834       78     
01782a6c 6587d834       90     
01782c7c 6587d834       68     
01783720 6587e388       64     
01783760 6587e388       64     
01783e4c 6587d834       62     

Statistics:
      MT    Count    TotalSize Class Name
6587e388        3          212 System.String[]
6587d834       12          914 System.String
Total 15 objects

如果有人出于某种原因需要地址和大小,总是可以 awk

0:004> .shell -ci "!DumpHeap -type System.String -min 0n62 -max 0n106" awk "{print $1,$3}"

Address Size
01781280 76
01781354 78
017813e8 62
01781478 84
017816d8 64
01781898 106
01781998 78
017819e8 70
01781a30 82
01782974 78
01782a6c 90
01782c7c 68
01783720 64
01783760 64
01783e4c 62

【讨论】:

  • Steve 后来删除了他的回复,因为 dumpheap 不提供包含大小,而根据问题,需要包含对象的大小。
  • 我不确定是否会本地调用awk
  • 肯定有 awk 克隆扩展 iirc mex ?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-03
  • 2019-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-07
相关资源
最近更新 更多