Сколько памяти использует объект С#/.NET?

Я разрабатываю приложение, в котором в настоящее время созданы сотни объектов.

Можно ли определить (или приблизительное) память, выделенную объектом (экземпляр класса)?

Ответ 2

Грубым способом может быть это в случае, если вы хотите знать, что происходит с конкретным объектом.

// Measure starting point memory use
GC_MemoryStart = System.GC.GetTotalMemory(true);

// Allocate a new byte array of 20000 elements (about 20000 bytes)
MyByteArray = new byte[20000];

// Obtain measurements after creating the new byte[]
GC_MemoryEnd = System.GC.GetTotalMemory(true);

// Ensure that the Array stays in memory and doesn't get optimized away
GC.KeepAlive(MyByteArray);

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

long Process_MemoryStart = 0;
Process MyProcess = System.Diagnostics.Process.GetCurrentProcess();
Process_MemoryStart = MyProcess.PrivateMemorySize64;

надеюсь, что это поможет;)

Ответ 3

Профайлер памяти ANTS расскажет вам, сколько всего выделено для каждого объекта/метода/и т.д.

Ответ 5

Вы также можете использовать WinDbg и SOS или SOSEX (например, SOS с большим количеством команд, а некоторые из существующих улучшены). Расширения WinDbg. Команда, которую вы будете использовать для анализа объекта по определенному адресу памяти: objsize

Один ОЧЕНЬ важный элемент, который нужно запомнить: objsize дает только размер самого класса и НЕ обязательно включает в себя размер совокупных объектов, содержащихся внутри класса, - я понятия не имею, почему это не делает это как это довольно неприятно и вводит в заблуждение время от времени.

Я создал 2 предложения Feature на веб-сайте Connect, которые просят включить эту возможность в VisualStudio. Пожалуйста, проголосуйте за предметы, которые вы хотели бы видеть, добавив их!

https://connect.microsoft.com/VisualStudio/feedback/details/637373/add-feature-to-debugger-to-view-an-objects-memory-footprint-usage

https://connect.microsoft.com/VisualStudio/feedback/details/637376/add-feature-to-debugger-to-view-an-objects-rooted-references

EDIT: Я добавляю следующее, чтобы уточнить некоторые данные из ответа, предоставленного Чарльзом Бретаной:

  • ОП спросил о размере "объекта", а не "класса". Объект является экземпляром класса. Возможно, это то, что вы имели в виду?
  • Память, выделенная для объекта, не включает код JIT. Код JIT живет в собственной "JIT Code Heap".
  • JIT только компилирует код на основе метода методом - не на уровне класса. Поэтому, если метод никогда не вызывается для класса, он никогда не компилируется JIT и, следовательно, никогда не выделяет память для него в куче кода JIT.

В стороне, есть около 8 разных куч, которые использует CLR:

  • Куча загрузчика: содержит структуры CLR и систему типов
  • Высокочастотная куча: статика, Таблицы методов, FieldDescs, карта интерфейса
  • Низкочастотная куча: таблицы EEClass, ClassLoader и таблицы поиска
  • Stub Heap: заглушки для CAS, COM-обертки, P/Invoke
  • Большая куча объектов: распределения памяти, для которых требуется более 85 тыс. байт.
  • GC Heap: выделенная пользователем куча памяти, приватная для приложения
  • JIT Code Heap: память, выделенная mscoreee (Execution Engine) и JIT-компилятор для управляемого кода
  • Process/Base Heap: interop/неуправляемые распределения, встроенная память и т.д.

НТН

Ответ 6

Каждый "класс" требует достаточно памяти для хранения всего этого jit-скомпилированного кода для всех его членов, которые были вызваны средой выполнения (хотя, если вы не назовете метод довольно долгое время, CLR может освободить что память и повторная запись снова, если вы снова назовете... плюс достаточно памяти для хранения всех статических переменных, объявленных в классе... но эта память выделяется только один раз для каждого класса, независимо от того, сколько экземпляров класса вы создать.

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

ссылочные переменные (ссылки на другие объекты) принимают 4 или 8 байтов (32/64 бит ОС?) int16, Int32, Int64 принимают 2,4 или 8 байтов, соответственно...

строковая переменная принимает дополнительное хранилище для некоторых элементов метаданных (плюс размер указателя адреса)

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

и т.д.. и др.

Ответ 7

Чтобы получить общий смысл для распределения памяти в вашем приложении, используйте следующую команду sos в WinDbg

!dumpheap -stat

Обратите внимание, что! dumpheap дает только байты самого типа объекта и не включает байты любых других типов объектов, которые он может ссылаться.

Если вы хотите увидеть общие удерживаемые байты (суммировать все байты всех объектов, на которые ссылается ваш объект) определенного типа объекта, используйте профайлер памяти, например, dot Trace - http://www.jetbrains.com/profiler/

Ответ 8

Если вы можете - Сериализовать его!

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

Существует академический вопрос Каков размер объекта во время выполнения?. И это интересно, но на него можно ответить только профилировщиком, подключенным к запущенному процессу. Я довольно долго смотрел на это недавно и решил, что нет универсального метода, который бы был точным и достаточно быстрым, чтобы вы когда-либо захотели использовать его в производственной системе. Простые случаи, такие как массивы числовых типов, имеют легкие ответы, но помимо этого лучший ответ будет Не утруждайте себя попыткой его выработать. Почему вы хотите это знать? Есть ли другая информация, которая может служить той же цели?

В моем случае я решил ответить на этот вопрос, потому что у меня были разные данные, которые были полезны, но их можно было отбросить, чтобы освободить ОЗУ для более важных сервисов. Мальчиками-плакатами здесь являются Undo Stack и Cache.

В конце концов я пришел к выводу, что правильный способ управления размером стека отмены и кеша состоял в том, чтобы запрашивать объем доступной памяти (это 64-битный процесс, поэтому можно предположить, что он доступен), а затем разрешить добавление большего количества элементов, если имеется достаточно большой буфер ОЗУ и требуется, чтобы элементы были удалены, если ОЗУ работает на низком уровне.