sos.dll和内存进程大小返回的对象大小不匹配

时间:2010-02-23 07:43:06

标签: .net clr windbg sos

我使用以下sos命令枚举正在运行的asp应用程序中的特定类型的所有实例(托管在Windows xp 4 GB计算机上)。

.foreach (obj { !dumpheap -type ::my type:: -short ::start of address space:: ::end of address space:: }) { !objsize ${obj} }.

这枚举了gc gen2中给定类型的所有对象。

对象大小平均约为500 KB,大约有2000个对象。仅此一项就增加了大约1 GB的内存,而我的任务管理器中的asp进程内存仅显示大约700 MB。还有一点是我没有考虑过我正在使用的其他加载对象。

此外,上述所有对象都是不会被垃圾回收的根对象。不确定此命令是否错误,或者是否存在sos返回的大小不匹配以及任务管理器中显示的内容的任何其他解释?

提前致谢,
Bharath K。

1 个答案:

答案 0 :(得分:3)

!objsize计算实例的大小,包括其所有引用的对象,因此如果您有任何共享对其他对象的引用的对象,则这些对象的大小将被计数多次。最常见的来源可能是字符串,因为文字字符串是固定的,因此使用相同的文字文本在对象之间共享。但是,您可能还有引用相同对象的集合。在任何情况下,总和将是不正确的,除非计算的对象根本不共享任何引用。

考虑这个例子

class SomeType {
    private readonly string Text;

    public SomeType(string text) {
        Text = text;
    }
}

和此代码

var st1 = new SomeType("this is a long string that will be stored only once due to interning");
var st2 = new SomeType("this is a long string that will be stored only once due to interning");

在WinDbg中

0:006> !dumpheap -type Some
 Address       MT     Size
00ceb44c 00b738a8       12     
00ceb458 00b738a8       12     

0:006> !objsize 00ceb44c
sizeof(00ceb44c) =          164 (        0xa4) bytes (TestApp.SomeType)
0:006> !objsize 00ceb458
sizeof(00ceb458) =          164 (        0xa4) bytes (TestApp.SomeType)

0:006> !DumpObj 00ceb44c
Name:        TestApp.SomeType
MethodTable: 00b738a8
EEClass:     00b714bc
Size:        12(0xc) bytes
File:        c:\dev2010\FSharpLib\TestApp\bin\Release\TestApp.exe
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
79b9d2b8  4000001        4        System.String  0 instance 00ceb390 Text
0:006> !DumpObj 00ceb458
Name:        TestApp.SomeType
MethodTable: 00b738a8
EEClass:     00b714bc
Size:        12(0xc) bytes
File:        c:\dev2010\FSharpLib\TestApp\bin\Release\TestApp.exe
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
79b9d2b8  4000001        4        System.String  0 instance 00ceb390 Text

正如您从!dumpobj的输出中看到的那样,它们都共享相同的引用,因此如果您将上面的!objsize报告的大小相加,则字符串将被计算两次。