Сколько памяти использует объект C # / .NET? - PullRequest
51 голосов
/ 09 января 2009

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

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

Ответы [ 9 ]

39 голосов
/ 09 января 2009

Вы можете использовать профилировщик памяти как

.NET Memory Profiler (http://memprofiler.com/)

или

CLR Profiler (бесплатно) (http://clrprofiler.codeplex.com/)

37 голосов
/ 25 апреля 2009

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

// 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;

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

11 голосов
/ 09 января 2009

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

10 голосов
/ 09 января 2009

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

7 голосов
/ 09 марта 2011

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

Один ОЧЕНЬ важный пункт, который нужно помнить, это то, что! Objsize дает вам только размер самого класса и НЕ ОБЯЗАТЕЛЬНО включает в себя размер агрегатных объектов, содержащихся в классе - я понятия не имею, почему он не делает это как иногда это довольно неприятно и вводит в заблуждение.

Я создал 2 предложения функций на веб-сайте 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: Я добавляю следующее, чтобы уточнить некоторую информацию из ответа Чарльза Бретана:

  1. ФП спросил о размере «объекта», а не «класса». Объект является экземпляром класса. Может это ты и имел ввиду?
  2. Память, выделенная для объекта, не включает код JITted. Код JIT живет в своей собственной «куче кода JIT».
  3. JIT компилирует код только на основе метода, а не на уровне класса. Поэтому, если метод никогда не вызывается для класса, он никогда не компилируется JIT и, следовательно, никогда не выделяется память для него в куче кода JIT.

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

  1. Loader Heap: содержит структуры CLR и систему типов
  2. Высокочастотная куча: статика, MethodTables, FieldDescs, карта интерфейса
  3. Низкочастотная куча: EEClass, ClassLoader и справочные таблицы
  4. Stub Heap: заглушки для CAS, оболочек COM, P / Invoke
  5. куча больших объектов: выделения памяти, для которых требуется более 85 Кбайт
  6. GC Heap: пользователь выделил кучу памяти для приложения
  7. JIT Code Heap: память, выделенная mscoreee (механизм выполнения) и JIT-компилятором для управляемого кода
  8. Process / Base Heap: взаимодействие / неуправляемые выделения, собственная память и т. Д.

НТН

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

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

!dumpheap -stat

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

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

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

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

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

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

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

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

и т.д.. и т.д.

5 голосов
/ 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
1 голос
/ 09 декабря 2015

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

В моем случае я захотел ответить на этот вопрос, потому что у меня были различные данные, которые были полезны, но их можно было отбросить, чтобы освободить ОЗУ для более важных служб. Парни с постером здесь: стек отмены и кеш .

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

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