What is the memory layout of a .NET array?
Take for instance this array:
Int32[] x = new Int32[10];
I understand that the bulk of the array is like this:
0000111122223333444455556666777788889999
Where each character is one byte, and the digits corresponds to indices into the array.
Additionally, I know that there is a type reference, and a syncblock-index for all objects, so the above can be adjusted to this:
ttttssss0000111122223333444455556666777788889999
^
+- object reference points here
Additionally, the length of the array needs to be stored, so perhaps this is more correct:
ttttssssllll0000111122223333444455556666777788889999
^
+- object reference points here
Is this complete? Are there more data in an array?
The reason I'm asking is that we're trying to estimate how much memory a couple of different in-memory representations of a rather large data corpus will take and the size of the arrays varies quite a bit, so the overhead might have a large impact in one solution, but perhaps not so much in the other.
So basically, for an array, how much overhead is there, that is basically my question.
And before the arrays are bad squad wakes up, this part of the solution is a static build-once-reference-often type of thing so using growable lists is not necessary here.
One way to examine this is to look at the code in WinDbg. So given the code below, let's see how that appears on the heap.
var numbers = new Int32[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
The first thing to do is to locate the instance. As I have made this a local in Main()
, it is easy to find the address of the instance.
From the address we can dump the actual instance, which gives us:
0:000> !do 0x0141ffc0
Name: System.Int32[]
MethodTable: 01309584
EEClass: 01309510
Size: 52(0x34) bytes
Array: Rank 1, Number of elements 10, Type Int32
Element Type: System.Int32
Fields:
None
This tells us that it is our Int32 array with 10 elements and a total size of 52 bytes.
Let's dump the memory where the instance is located.
0:000> d 0x0141ffc0
0141ffc0 [84 95 30 01 0a 00 00 00-00 00 00 00 01 00 00 00 ..0.............
0141ffd0 02 00 00 00 03 00 00 00-04 00 00 00 05 00 00 00 ................
0141ffe0 06 00 00 00 07 00 00 00-08 00 00 00 09 00 00 00 ................
0141fff0 00 00 00 00]a0 20 40 03-00 00 00 00 00 00 00 00 ..... @.........
01420000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
01420010 10 6d 99 00 00 00 00 00-00 00 01 40 50 f7 3d 03 .m.........@P.=.
01420020 03 00 00 00 08 00 00 00-00 01 00 00 00 00 00 00 ................
01420030 1c 24 40 03 00 00 00 00-00 00 00 00 00 00 00 00 .$@.............
I have inserted brackets for the 52 bytes.
Edit: Forgot length in first posting.
The listing is slightly incorrect because as romkyns points out the instance actually begins at the address - 4 and the first field is the Syncblock.