!objsize
calculates the size of an instance including all its referenced objects, so if you have any objects that share references to other objects the size of these will be counted multiple times. The most common source for this is probably strings, as literal strings are interned and thus shared among objects using the same literal text. However, you may also have collections referencing the same objects. In any case, the sum will be incorrect unless the counted objects do not share any references at all.
Consider this example
class SomeType {
private readonly string Text;
public SomeType(string text) {
Text = text;
}
}
and this code
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");
In 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
As you can see from the output of !dumpobj
, they both share the same reference, so if you sum the size as reported by !objsize
above, the string is counted twice.