Как проще всего узнать, сколько памяти использует объект в .NET?

Как проще всего узнать, сколько памяти использует объект в .NET?

Желательно без использования сторонних инструментов. Операторы Marshal.SizeOf или sizeof выглядят полезными, но работают только с ограниченным диапазоном типов.

Некоторые связанные сообщения:

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
757
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Спросил и ответил здесь: Определить, сколько памяти использует класс?

Вкратце, если вы не хотите использовать инструмент, вам нужно использовать .NET Profiling API

API-интерфейс профилирования невероятно мощный, но я не думаю, что его можно назвать «простым», поэтому я настоятельно рекомендую использовать инструмент профилирования памяти - есть некоторые бесплатные, которые подходят, а некоторые нет. - слишком дорогие коммерческие (в частности, JetBrains dotTrace), которые действительно хороши.

Ответ принят как подходящий

вы также можете сделать что-то вроде этого:

int startMem = GC.GetTotalMemory(true);
YourClass c = new YourClass();
int endMem = GC.GetTotalMemory(true);
int usedMeme = endMem - startMem;

Я сомневаюсь, что это сработает в общем случае. С одной стороны, выделение объекта может запустить новый цикл сборки мусора. Даже если вы вызываете GetTotalMemory (true), что-то может происходить в другом потоке, который влияет на результат.

Mark Bessey 01.10.2008 01:00

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

Marc Gravell 01.10.2008 01:01

Я не знаю ... Объедините это с проверкой GC.CollectionCount до и после, и вы, по крайней мере, сможете узнать, неточный ли ваш номер. Определенно соответствует легкому тесту лучше, чем Profiler API, и, вероятно, будет работать в 80% случае. +1 от меня.

Mark Brackett 23.10.2008 01:00

Похоже, это невозможно, но ответ Младена наиболее близок по всем его недостаткам 8)

Thomas Bratt 09.12.2009 02:07

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

Если ответ отрицательный, сложите размер всех полей: Используя отражение, выполните итерацию по всем членам класса; используйте Marshal.Sizeof (member.Type) для всего, что typeof (ValueType) .IsAssignableFrom (member.Type) - это измеряет примитивные типы и структуры, все из которых находятся в выделенном экземпляре класса. Каждый ссылочный тип (все, что нельзя присвоить типу значения) будет иметь IntPtr.Size. Есть отвратительное количество исключений из этого правила, но это может сработать для вас.

Если да, у вас серьезная проблема. Несколько вещей могут ссылаться на один экземпляр, поэтому, если 'a' и 'b' оба указывают на 'c', тогда RecursiveSizeOf(a) + RecursiveSizeOf(b) будет больше, чем SimpleSizeOf(a) + SimpleSizeOf(b) + SimpleSizeOf(c).

Хуже того, рекурсивное измерение может привести вас к круговым ссылкам или к объектам, которые вы не собираетесь измерять - например, если класс ссылается на мьютекс, этот мьютекс может указывать на поток, которому он принадлежит. Этот поток может указывать на все свои локальные переменные, которые указывают на некоторые структуры фреймворка C# ... вы можете в конечном итоге измерить всю свою программу.

Это может помочь понять, что язык со сборкой мусора, такой как C#, является несколько «нечетким» (в совершенно нетехническом смысле) в том, как он проводит различия между объектами и единицами памяти. Это многое из того, что смягчает Marshal - правила маршалинга гарантируют, что структура, которую вы маршалируете (или измеряете), имеет четко определенную структуру памяти и, следовательно, четко определенный размер. В этом случае вам следует использовать четко определенные маршалируемые структуры, если вы собираетесь использовать Marhsal.SizeOf ().

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

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

Другие вопросы по теме