Макет памяти для .NET-массива
Каков макет памяти для .NET-массива?
Возьмем, например, этот массив:
Int32[] x = new Int32[10];
Я понимаю, что основная масса массива такова:
0000111122223333444455556666777788889999
Если каждый символ является одним байтом, а цифры соответствуют индексам в массиве.
Кроме того, я знаю, что есть ссылка типа и индекс синхронизации для всех объектов, поэтому приведенное выше можно настроить следующим образом:
ttttssss0000111122223333444455556666777788889999
^
+- object reference points here
Кроме того, необходимо сохранить длину массива, поэтому, возможно, это более корректно:
ttttssssllll0000111122223333444455556666777788889999
^
+- object reference points here
Является ли это полным? Есть ли больше данных в массиве?
Причина, по которой я спрашиваю, заключается в том, что мы пытаемся оценить, сколько памяти будет иметь несколько различных представлений в памяти довольно большого массива данных, и размер массивов будет немного отличаться, поэтому накладные расходы может иметь большое влияние в одном решении, но, возможно, не так много в другом.
Итак, для массива, сколько накладных расходов есть, это в основном мой вопрос.
И до того, как массивы просыпаются плохим отрядом, эта часть решения является статическим строгом-раз-ссылкой-частотным типом, поэтому использование готовых списков здесь не требуется.
Ответы
Ответ 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
Объект массива должен хранить количество измерений и длину каждого измерения. Таким образом, есть еще один элемент данных для добавления в вашу модель.