Структура памяти массива .NET - PullRequest
40 голосов
/ 28 января 2009

Какова структура памяти массива .NET?

Возьмем, к примеру, этот массив:

Int32[] x = new Int32[10];

Я понимаю, что основная часть массива выглядит так:

0000111122223333444455556666777788889999

Где каждый символ - один байт, а цифры соответствуют индексам в массиве.

Кроме того, я знаю, что есть ссылка на тип и индекс syncblock для всех объектов, поэтому приведенное выше можно настроить следующим образом:

ttttssss0000111122223333444455556666777788889999
        ^
        +- object reference points here

Кроме того, необходимо сохранить длину массива, так что, возможно, это более правильно:

ttttssssllll0000111122223333444455556666777788889999
        ^
        +- object reference points here

Это завершено? Есть ли еще данные в массиве?

Причина, по которой я спрашиваю, состоит в том, что мы пытаемся оценить, сколько памяти займет несколько различных представлений в памяти довольно большого массива данных, и размер массивов варьируется довольно немного, поэтому накладные расходы может иметь большое влияние в одном решении, но, возможно, не так сильно в другом.

Так что, в основном, для массива, сколько накладных расходов, это в основном мой вопрос.

И до того, как массивы испортятся, отряд пробудится, эта часть решения является типом статической сборки один раз-ссылка-часто, поэтому использование растущих списков здесь не обязательно.

Ответы [ 4 ]

19 голосов
/ 28 января 2009

Один из способов проверить это - посмотреть код в WinDbg. Итак, учитывая приведенный ниже код, давайте посмотрим, как это выглядит в куче.

var numbers = new Int32[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

Первое, что нужно сделать, это найти экземпляр. Поскольку я сделал это локальным в Main(), легко найти адрес экземпляра.

С адреса мы можем вывести фактический экземпляр, что дает нам:

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

Это говорит нам о том, что это наш массив Int32 с 10 элементами и общим размером 52 байта.

Давайте выбросим память, в которой находится экземпляр.

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  .$@.............

Я вставил скобки для 52 байтов.

  • Первые четыре байта являются ссылкой на таблицу методов по адресу 01309584.
  • Затем четыре байта для длины массива.
  • После этого идут цифры от 0 до 9 (каждые четыре байта).
  • Последние четыре байта равны нулю. Я не совсем уверен, но я предполагаю, что именно там должна храниться ссылка на массив syncblock, если экземпляр используется для блокировки.

Редактировать: Забыл длину в первом сообщении.

Список немного некорректен, потому что, как указывает romkyns, экземпляр фактически начинается с адреса - 4, а первое поле - это Syncblock.

7 голосов
/ 28 января 2009

Отличный вопрос. Я нашел эту статью, которая содержит блок-схемы как для типов значений, так и для ссылочных типов. Также см. Эту статью , в которой Ритчер заявляет:

[snip] каждый массив имеет некоторые дополнительные служебная информация, связанная с Это. Эта информация содержит ранг массива (количество измерений), нижние оценки для каждого измерения массив (почти всегда 0) и длина каждого измерения. Накладные расходы также содержит тип каждого элемента в массиве.

6 голосов
/ 28 января 2009

Отличный вопрос! Я хотел убедиться в этом сам, и мне показалось, что это хорошая возможность попробовать CorDbg.exe ...

Похоже, что для простых целочисленных массивов формат:

ssssllll000011112222....nnnn0000

где s - блок синхронизации, l длина массива, а затем отдельные элементы. Кажется, что в конце есть наконец 0, я не уверен, почему это так.

Для многомерных массивов:

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

где s - блок синхронизации, t общее количество элементов, l1 длина первого измерения, l2 длина второго измерения, затем два нуля?, Затем последовательно следуют все элементы и, наконец, снова ноль .

Массивы объектов обрабатываются как целочисленный массив, содержимое на этот раз является ссылками. Зубчатые массивы - это массивы объектов, ссылки на которые указывают на другие массивы.

0 голосов
/ 28 января 2009

Объект массива должен хранить количество измерений и длину каждого измерения. Таким образом, есть еще как минимум один элемент данных для добавления в вашу модель

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...