Узнайте размер объекта .net - PullRequest
52 голосов
/ 27 ноября 2008

Я пытаюсь выяснить, сколько памяти занимают мои объекты, чтобы увидеть, сколько из них попадает в кучу больших объектов (что превышает 85 000 байт).

Это так же просто, как добавить 4 для целого, 8 для длинного, 4 (или 8, если у вас 64-битная версия) для любых ссылочных типов и т. Д. Для каждого объекта, или есть издержки для методов, свойств и т. Д.

Ответы [ 7 ]

52 голосов
/ 27 ноября 2008

Не забывайте, что размер реального объекта не включает размер любых объектов, на которые он ссылается.

Единственные вещи, которые могут оказаться в куче больших объектов, - это массивы и строки - другие объекты, как правило, относительно малы сами по себе. Даже объект с (скажем) 10 переменными ссылочного типа (4 байта каждая на x86) и 10 GUID (16 байтов каждая) будет занимать всего около 208 байтов (для блока ссылки на тип и синхронизации есть некоторые издержки).

Точно так же, думая о размере массива, не забывайте, что если тип элемента является ссылочным типом, то для самого массива учитывается только размер ссылок . Другими словами, даже если у вас есть массив с 20 000 элементов, размер самого объекта массива будет чуть более 80 КБ (на x86), даже если он ссылается на гораздо больше данных.

35 голосов
/ 19 августа 2011

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

1) перейдите в Visual Studio (2010) Свойства проекта -> вкладка Отладка -> Включить отладку неуправляемого кода.

2) перейдите в меню «Отладка Visual Studio» -> «Параметры и настройки» -> «Отладка» -> «Символы».

3) Включите Microsoft Symbol Server, оставьте значение по умолчанию (символы могут начать загрузку)

4) Установите точку останова в вашем коде, начните отладку (F5).

5) Откройте Debug -> Windows -> Немедленное окно.

6) введите .load sos.dll (сын удара)

7) введите! DumpHeap -type MyClass (объект, размер которого вы хотите найти)

8) из выходного адреса найдите адрес объекта, т.е. (00a8197c)

Адрес MT Размер 00a8197c 00955124 36

9) Далее,! ObjSize 00a8197c

10) Вот и все -> sizeof (00a8197c) = 12 (0x48) байт (MyClass)

9 голосов
/ 05 июля 2011

Если можешь - сериализуй!

Dim myObjectSize As Long

Dim ms As New IO.MemoryStream
Dim bf As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
bf.Serialize(ms, myObject)
myObjectSize = ms.Position
9 голосов
/ 28 ноября 2008

Вы попадаете в область расширенной отладки .NET. Начните с отладочных книг Джона Робинса .

Используйте WinDBG с Sos.dll (часть дистрибутива .NET) и Sosex.dll с расширениями. С помощью этих инструментов вы действительно можете видеть, что происходит, когда ваше приложение работает. Вы найдете ответы на свои вышеупомянутые вопросы.

(Еще одна рекомендация - установить Shared Source CLI 2.0 , он же. Rotor 2, чтобы увидеть, что происходит под капотом.)

5 голосов
/ 26 марта 2012

Метод Гомеса упрощен:

  1. перейдите в Visual Studio (2010) Свойства проекта -> вкладка Отладка -> Включить отладку неуправляемого кода.

  2. Установите точку останова в вашем коде, начните отладку (F5).

  3. Открыть Отладка -> Windows -> Немедленное окно.

  4. введите .load SOS

  5. введите (замените myObject именем вашего объекта)

? String.Format ( "{0: X}", Integer.Parse (System.Runtime.InteropServices.GCHandle.InternalAddrOfPinnedObject (System.Runtime.InteropServices.GCHandle.Alloc ( MyObject ) GetHandleValue ()).. Нанизывать()) - 4)

6. Используйте результат в качестве параметра! ObjSize

см .: SOS.DLL, адрес объекта и отладчик Visual Studio Введение

Пример (мы ищем объект с именем tbl):

.load sos
extension C:\Windows\Microsoft.NET\Framework\v4.0.30319\sos.dll loaded
? string.Format("{0:x}",Integer.Parse(System.Runtime.InteropServices.GCHandle.InternalAddrOfPinnedObject(System.Runtime.InteropServices.GCHandle.Alloc(tbl).GetHandleValue()).ToString())-4)
"27ccb18"
!ObjSize 27ccb18
PDB symbol for clr.dll not loaded
sizeof(027ccb18) =       154504 (     0x25b88) bytes (System.Data.DataTable)
4 голосов
/ 27 ноября 2008

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

.NET (в настоящее время) выравнивает типы почти так же, как нативные компиляторы выравнивают типы. Фундаментальные типы имеют естественные выравнивания, которые, как правило, представляют собой округленную интегральную степень двух ближайших к их размеру:

Single, Int32, UInt32 - 4
IntPtr, UIntPtr, pointers, references  - 4 on 32-bit, 8 on 64-bit
Double, Int64, UInt64 - 8
Char, Int16, UInt16   - 2
Byte, SByte           - 1

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

Сами определяемые пользователем типы имеют выравнивание, которое рассчитывается как наибольшее выравнивание среди всех типов полей. Размер шрифта увеличивается при необходимости, чтобы размер шрифта был выровнен.

Но, конечно, все ссылочные типы по-прежнему имеют размер и выравнивание только IntPtr.Size, поэтому размер ссылочного типа не повлияет на массивы этого типа.

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

0 голосов
/ 31 августа 2017

В качестве оценки (в 2017 году) вы можете выполнить отладку в своем приложении, установить точку останова до запуска словаря, сделать «Снимок использования памяти» (вкладка «Использование памяти» в разделе «Инструменты диагностики»), заполнить словарь и получить другой Снимок - не точно, положите хорошую оценку.

...