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





Спросил и ответил здесь: Определить, сколько памяти использует класс?
Вкратце, если вы не хотите использовать инструмент, вам нужно использовать .NET Profiling API
API-интерфейс профилирования невероятно мощный, но я не думаю, что его можно назвать «простым», поэтому я настоятельно рекомендую использовать инструмент профилирования памяти - есть некоторые бесплатные, которые подходят, а некоторые нет. - слишком дорогие коммерческие (в частности, JetBrains dotTrace), которые действительно хороши.
вы также можете сделать что-то вроде этого:
int startMem = GC.GetTotalMemory(true);
YourClass c = new YourClass();
int endMem = GC.GetTotalMemory(true);
int usedMeme = endMem - startMem;
Это невероятно хрупко; в любой нетривиальной настройке вы не можете гарантировать, что больше ничего не произойдет. Поток и т. д.
Я не знаю ... Объедините это с проверкой GC.CollectionCount до и после, и вы, по крайней мере, сможете узнать, неточный ли ваш номер. Определенно соответствует легкому тесту лучше, чем Profiler API, и, вероятно, будет работать в 80% случае. +1 от меня.
Похоже, это невозможно, но ответ Младена наиболее близок по всем его недостаткам 8)
Из-за того, что .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 ().
Другой вариант - сериализация. Это не скажет вам конкретно, сколько памяти используется, но даст вам относительное представление о размере объекта. Но опять же, чтобы сериализовать вещи, они должны иметь четко определенный макет (и, следовательно, четко определенный размер) - вы можете добиться этого, сделав класс соответствующим образом сериализуемым.
Я могу опубликовать примеры реализации, если вам понравится какой-либо из вышеперечисленных вариантов.
Я сомневаюсь, что это сработает в общем случае. С одной стороны, выделение объекта может запустить новый цикл сборки мусора. Даже если вы вызываете GetTotalMemory (true), что-то может происходить в другом потоке, который влияет на результат.