Почему результат "Просмотр кучи" не соответствует "Использование памяти процесса" в Visual Studio

Я пытаюсь использовать Visual Studio для отслеживания использования памяти в моем приложении. В окне "Средства диагностики" показано, что мое приложение использует 423 МБ. Спасибо, я перехожу к "Использование памяти" и "ViewHeap", когда я нажимаю на снимок, я получаю таблицу размеров моих объектов.

enter image description here

Но когда я добавлю это число:

= 3317228 
+  403764
+  354832
+  264984
+  244836
+  195748
+  144032
+   28840
+   16452
+   13920
+   13888
+    3428
+    2100
+      20
= 5004072
= 4.77 MB

Мой вопрос: почему это число 4,77 МБ не совпадает с 423 МБ, которые я вижу на диаграмме "Память". Я ожидаю увидеть таблицу слева с разбивкой, куда ушло 423 МБ. Пожалуйста, скажите мне, что мне не хватает?

Ответы

Ответ 1

Почему размер области просмотра не соответствует размеру диаграммы памяти?

Для этого существуют десятки потенциальных причин, в том числе JITter, Инструменты отладки, Отладочные символы, Только мой код, Сбор мусора и др. Мы пройдем через два из больших.

Только мой код

Функция Только мой код Visual Studio имеет тенденцию скрывать от пользователя выделения, исключения, точки останова и любые другие метаданные, отличные от кода, которые не были загружены из файла .PDB или открытый проект. Подробнее см. MSDN Just My Code.

Отладка символов и инструментов

При отладке любого проекта в Visual Studio отладчик Visual Studio запускает и выделяет дополнительную память, чтобы разрешать точки останова, catch catch и другие функции. Для правильной записи диагностических инструментов вы должны использовать параметр Alt+F2 или Отладкa > Начать диагностические инструменты без отладки.... Вы также захотите переключиться на Освободить режим для этой части. Только этот шаг сократил память, которую показал график (для меня) от 21.5MiB до 5.5MiB, что указывает на Отладочные символы и Инструменты отладки существенные. Помните, что для того, чтобы Visual Studio могла улавливать исключения, точки останова и другие данные, он должен присоединяться к вашему процессу и ко всем объектам в вашем процессе.

Итак, как мы можем сопоставить эти числа?

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

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

Поистине соответствие номеров

Если вы действительно хотите их сопоставить, я не думаю, что это можно сделать так, как вы пожелаете. Однако вы можете приблизиться. Первым шагом является Запустить диагностические инструменты без отладки..., затем выберите Использование памяти. После этого выберите Настройки Gear рядом с ним и убедитесь, что Тип профиля Mixed (Managed and Native). Затем нажмите Начать и сделайте несколько снимков, чтобы изучить возможность использования памяти. После этого остановите свою отладку и изучите свою память.

Чтобы проверить свою память, нажмите синий верхний левый синий номер в снимке для моментального снимка, который вы хотите изучить. На этой странице щелкните значок Grid Icon на вверху справа и снимите выделение Только мой код и Свернуть малые объекты. > . Перейдите на вкладку Нативная куча и сделайте то же самое, отменив выбор Только мой код, а затем выберите "Включить освобожденные выделения" .

Вы должны обнаружить, что это само по себе привносит вашу ошибку в соответствие с фактическим значением. (Фактическое значение Частные байты, а ошибка - Размер кучи). С приложением, в котором я тестировал его, он привел общее количество (от обеих куч) до примерно 1.0265MiB, что было примерно таким же, как выделение, указанное Диспетчером задач, когда я запускал программу вне Visual Studio (это фактическое значение было 1.1211MiB, но с номерами, это небольшое, что погрешность ожидается).

Что означает Включить Освобожденные распределения? По сути, когда GC очищает память, эта память не удаляется сразу из пространства приложения. Вместо этого он освобождается для использования другими объектами, но может оставаться с приложением. Garbage Collection - сложная тема и выходит за рамки этого вопроса и ответа.

Дополнительные примечания

Распределение памяти, использование и измерение - очень сложная тема. К сожалению, существует не так много 100% надежных способов решения подобных ситуаций, и, как правило, более надежное и точное решение, более сложное, медленное и сложное в использовании.

Ссылки

MSDN Только мой код: https://msdn.microsoft.com/en-us/library/dn457346.aspx#BKMK__NET_Framework_Just_My_Code

MSDN Garbage Collection: https://msdn.microsoft.com/en-us/library/0xy59wtx%28v=vs.110%29.aspx

Остальная часть этого ответа основана на моих собственных экспериментах, проб и ошибок и подвержена потенциальным неточностям, которые могут возникнуть в разных средах. Представленные здесь шаги могут не работать для всех разработчиков и выполнялись с помощью версии Visual Studio 2015 RC версии 14.0.22823.1 D14REL.

Ответ 2

На графике показаны частные байты для всего процесса. Это включает в себя управляемую кучу, собственную кучу, стеки и т.д. См. Этот ответ для получения дополнительных сведений о типах метрик памяти: Что такое личные байты, виртуальные байты, рабочий набор?

В таблице "Вид кучи" отображаются только те типы, которые активны (не могут быть собраны в мусор) в управляемой куче во время моментального снимка. Чтобы просмотреть типы как на родной, так и управляемой кучи, переключитесь на отладку в смешанном режиме. Вид кучи (и число в таблице снимков) являются подмножеством памяти процесса, показанной на графике.

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

Здесь сообщение в блоге, которое я написал (я работаю для MSFT) в инструменте памяти, объясняя, как отслеживать объекты с устаревшими ссылками: http://blogs.msdn.com/b/visualstudioalm/archive/2015/04/29/diagnosing-event-handler-leaks-with-the-memory-usage-tool-in-visual-studio-2015.aspx