Подтвердить что ты не робот

Макет памяти для .NET-массива

Каков макет памяти для .NET-массива?

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

Int32[] x = new Int32[10];

Я понимаю, что основная масса массива такова:

0000111122223333444455556666777788889999

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

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

ttttssss0000111122223333444455556666777788889999
        ^
        +- object reference points here

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

ttttssssllll0000111122223333444455556666777788889999
        ^
        +- object reference points here

Является ли это полным? Есть ли больше данных в массиве?

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

Один из способов изучить это - посмотреть на код в 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  [email protected]=.
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  [email protected]

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

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

Изменить: Забыть длину в первой публикации.

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

Ответ 3

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

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

ssssllll000011112222....nnnn0000

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

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

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

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

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

Ответ 4

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