1

One of class has many object present in .NET heap as discovered through following sos command.

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

I need to find the instances of those objects that have ObjSize greater then 5 MB. I know I can list out objsize of all 1700 instances of MyClass using following.

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

With the script above, I don't get any results although there are object instances greater than 5MB. I think problem may be that output of objsize is follows

20288 (0x4f40) bytes

Its a string which make it harder to compare against any threshold. How can I get this script to only list objects that has objsize larger then 5MB?

whoami
  • 1,689
  • 3
  • 22
  • 45

2 Answers2

1

Creating complex scripts in WinDbg is quite error prone. In such situations, I switch to PyKd, which is a WinDbg extension that uses Python.

In the following, I'll only cover the missing piece in your puzzle, which is the parts that does not work:

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

Here's my starting point:

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

You can write a script like this (no error handling!)

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

and use it within your loop:

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

Note how the size of !objsize differs from that of !dumpheap. Just for cross-checking:

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

See also this answer on how to improve the script using expr() so that you can pass expressions etc. The way I did it now outputs the size in decimal, but that's not explicit. Maybe you want to output a 0n prefix to make it clear.

Community
  • 1
  • 1
Thomas Weller
  • 55,411
  • 20
  • 125
  • 222
  • Good point. I'll include it, however, what I am asking here is how to compare return value of objsize containing size in decimal, hex and unit(bytes) ) against a threshold. – paul deter Oct 20 '16 at 11:54
0

well as Steve Commented !dumpeap takes a min and max parameter and with those it should be possible to do it natively

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

manipulating max,min we can fine tune to just one or two objects
an example where we have 1 object extra on upper side and 2 objects extra on lower side
from output preceding this (15 objects versus 12 objects)

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

if one needs the address and size both for some reason one could always awk it

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
blabb
  • 8,674
  • 1
  • 18
  • 27