Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory layout of a .NET array

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.

like image 936
Lasse V. Karlsen Avatar asked Jan 28 '09 10:01

Lasse V. Karlsen


People also ask

What is memory layout of array?

The elements of an array can be stored in column-major layout or row-major layout. For an array stored in column-major layout, the elements of the columns are contiguous in memory. In row-major layout, the elements of the rows are contiguous. Array layout is also called order, format, and representation.

How much memory does an array use C#?

C# arrays are stored by reserving a block of memory that equals the amount needed to hold the elements. If you store five integers that each take up four bytes of memory, the runtime allocates 20 bytes of memory (4 x 5) to hold the values.

What is the size in memory of array?

The memory allocation for an array includes the header object of 12 bytes plus the number of elements multiplied by the size of the data type that will be stored and padding as needed for the memory block to be a multiple of 8 bytes.

Do arrays take up memory?

Unless it's a VLA, array size is a compile time constant, so it does not matter how much memory you're actually using, it will take up the amount of memory same as the size of the array given at the time of definition.


3 Answers

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.

  • The first four bytes are the reference to the method table at 01309584.
  • Then four bytes for the Length of the array.
  • Following that are the numbers 0 to 9 (each four bytes).
  • The last four bytes are null. I'm not entirely sure, but I guess that must be where the reference to the syncblock array is stored if the instance is used for locking.

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.

like image 121
Brian Rasmussen Avatar answered Oct 03 '22 21:10

Brian Rasmussen


Great question. I found this article which contains block diagrams for both value types and reference types. Also see this article in which Ritcher states:

[snip] each array has some additional overhead information associated with it. This information contains the rank of the array (number of dimensions), the lower bounds for each dimension of the array (almost always 0), and the length of each dimension. The overhead also contains the type of each element in the array.

like image 44
ng5000 Avatar answered Oct 03 '22 22:10

ng5000


Great question! I wanted to see it for myself, and it seemed a good opportunity to try out CorDbg.exe...

It seems that for simple integer arrays, the format is:

ssssllll000011112222....nnnn0000

where s is the sync block, l the length of the array, and then the individual elements. It seems that there is a finally 0 at the end, I'm not sure why that is.

For multidimensional arrays:

ssssttttl1l1l2l2????????
    000011112222....nnnn000011112222....nnnn....000011112222....nnnn0000

where s is the sync block, t the total number of elements, l1 the length of the first dimension, l2 the length of the second dimension, then two zeroes?, followed by all the elements sequentially, and finally a zero again.

Object arrays are treated as the integer array, the contents are references this time. Jagged arrays are object arrays where the references point to other arrays.

like image 28
Eric Minkes Avatar answered Oct 03 '22 21:10

Eric Minkes