本文摘录自stackoverflow的一个问题overhead-of-a-net-array
下面列出要点:
Consider the following code
var strings = new string[1]; var ints = new int[1]; strings[0] = "hello world"; ints[0] = 42;
Attaching WinDbg shows the following:
First let‘s take a look at the value type array.
0:000> !dumparray -details 017e2acc Name: System.Int32[] MethodTable: 63b9aa40 EEClass: 6395b4d4 Size: 16(0x10) bytes Array: Rank 1, Number of elements 1, Type Int32 Element Methodtable: 63b9aaf0 [0] 017e2ad4 Name: System.Int32 MethodTable 63b9aaf0 EEClass: 6395b548 Size: 12(0xc) bytes (C:\Windows\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll) Fields: MT Field Offset Type VT Attr Value Name 63b9aaf0 40003f0 0 System.Int32 1 instance 42 m_value <=== Our value 0:000> !objsize 017e2acc sizeof(017e2acc) = 16 ( 0x10) bytes (System.Int32[]) 0:000> dd 017e2acc -0x4 017e2ac8 00000000 63b9aa40 00000001 0000002a <=== That‘s the value
First we dump the array and the one element with value of 42. As can be seen the size is 16 bytes. That is 4 bytes for the int32
value itself, 8 bytes for regular reference type overhead and another 4 bytes for the length of the array.
The raw dump shows the SyncBlock, the method table for int[]
, the length, and the value of 42 (2a in hex). Notice that the SyncBlock is located just in front of the object reference.
Next, let‘s look at the string[]
to find out what the additional word is used for.
0:000> !dumparray -details 017e2ab8 Name: System.String[] MethodTable: 63b74ed0 EEClass: 6395a8a0 Size: 20(0x14) bytes Array: Rank 1, Number of elements 1, Type CLASS Element Methodtable: 63b988a4 [0] 017e2a90 Name: System.String MethodTable: 63b988a4 EEClass: 6395a498 Size: 40(0x28) bytes <=== Size of the string (C:\Windows\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll) String: hello world Fields: MT Field Offset Type VT Attr Value Name 63b9aaf0 4000096 4 System.Int32 1 instance 12 m_arrayLength 63b9aaf0 4000097 8 System.Int32 1 instance 11 m_stringLength 63b99584 4000098 c System.Char 1 instance 68 m_firstChar 63b988a4 4000099 10 System.String 0 shared static Empty >> Domain:Value 00226438:017e1198 << 63b994d4 400009a 14 System.Char[] 0 shared static WhitespaceChars >> Domain:Value 00226438:017e1760 << 0:000> !objsize 017e2ab8 sizeof(017e2ab8) = 60 ( 0x3c) bytes (System.Object[]) <=== Notice the underlying type of the string[] 0:000> dd 017e2ab8 -0x4 017e2ab4 00000000 63b74ed0 00000001 63b988a4 <=== Method table for string 017e2ac4 017e2a90 <=== Address of the string in memory 0:000> !dumpmt 63b988a4 EEClass: 6395a498 Module: 63931000 Name: System.String mdToken: 02000024 (C:\Windows\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll) BaseSize: 0x10 ComponentSize: 0x2 Number of IFaces in IFaceMap: 7 Slots in VTable: 196
First we dump the array and the string. Next we dump the size of the string[]
. Notice that WinDbg lists the type as System.Object[]
here. The object size in this case includes the string itself, so the total size is the 20 from the array plus the 40 for the string.
By dumping the raw bytes of the instance we can see the following: First we have the SyncBlock, then follows the method table for object[]
, then the length of the array. After that we find the additional 4 bytes with the reference to the method table for string. This can be verified by the dumpmt command as shown above. Finally we find the single reference to the actual string instance.
In conclusion
The overhead for arrays can be broken down as follows (on 32 bit that is)
- 4 bytes SyncBlock
- 4 bytes for Method table (type reference) for the array itself
- 4 bytes for Length of array
- Arrays of reference types adds another 4 bytes to hold the method table of the actual element type (reference type arrays are
object[]
under the hood)
I.e. the overhead is 12 bytes for value type arrays and 16 bytes for reference type arrays.