Отслеживание утечки памяти .NET Windows

Перед установкой моей службы Windows в производство я искал надежные тесты, которые я могу выполнить, чтобы убедиться, что мой код не содержит утечек памяти. Тем не менее, все, что я могу найти в сети, было с помощью диспетчера задач, чтобы посмотреть на используемую память или некоторые инструменты профилирования платной памяти.

Насколько я понимаю, просмотр диспетчера задач не очень полезен и не может подтвердить утечку памяти (в случае, если есть).

  • Как подтвердить, есть ли утечка памяти или нет?

  • Есть ли свободные инструменты для поиска источника утечек памяти?

Примечание. Я использую .Net Framework 4.6 и сообщество Visual Studio 2015

Ответ 1

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

Но...

Бесплатный инструмент - ".Net CLR profiler"

Есть бесплатный инструмент, и это от Microsoft, и это потрясающе. Это обязательное использование для всех программ, которые утечки ссылок. Поиск сайта MS.

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

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

У него даже есть крутая визуализация того, какие объекты выделяют какую память (чтобы вы могли отслеживать ошибки). Я считаю, что вам нужны объяснения, если вам нужно объяснение.

Визуализация использования памяти

Страница Википедии со ссылками для скачивания...

ПРИМЕЧАНИЕ. Вероятно, вам придется запускать приложение не как службу для его использования. Сначала он запускается, а затем запускается ваше приложение. Вы можете сделать это с помощью TopShelf или просто поместив кишки в DLL, которая запускается из EXE, что подразумевает интеграцию сервисов (шаблон хоста службы).

Ответ 2

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

Только один из многих примеров: неправильное использование одноразовых классов может привести к тому, что множество экземпляров потребуют памяти. Для службы Windows медленное, но постоянное увеличение экземпляров может в конечном итоге привести к значительному использованию памяти.

Да, есть инструмент для анализа утечек памяти. Это просто не бесплатно. Однако вы можете определить свою проблему в течение 7-дневного трейла.

Я предлагаю взять добычу в .NET Memory Profiler.

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

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

Однако вы можете использовать этот инструмент для интеграции потребления памяти в структуру unit test, например NUnit или MSTest.

Ответ 3

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

Вот некоторые из тех знаний, которые я собрал за эти годы:

  • Проверяйте свою службу как обычный исполняемый файл как можно больше. Попытка проверить обслуживание как фактическое обслуживание просто усложняет ситуацию.

  • Получите привычку явно отменить все, что вы делаете в конце сферы действия этой вещи, которую вы делаете. Например, если вы регистрируете наблюдателя в случае какого-либо наблюдателя, всегда должен быть какой-то момент времени (распоряжение наблюдателем или наблюдателем?), Что вы его не регистрируете. Теоретически сбор мусора должен позаботиться об этом, собирая весь график взаимосвязанных наблюдателей и наблюдений, но на практике, если вы не пинаете привычку забывать об отмене того, что вы делаете, вы получаете утечки памяти.

  • Используйте IDisposable как можно больше и сообщайте своим деструкторам, если кто-то забыл вызвать Dispose(). Подробнее об этом методе здесь: Обязательное удаление против мерзости "Dispose-disposing" Раскрытие информации: Я являюсь автором этой статьи.

  • У вас есть регулярные контрольные точки в вашей программе, где вы отпускаете все, что должно быть доступно (как если бы программа выполняла упорядоченное завершение, чтобы завершить работу), а затем принудительно собрала мусор, чтобы увидеть, есть ли у вас какие-либо утечки.

  • Если экземпляры какого-либо класса кажутся утечками, используйте следующий трюк, чтобы обнаружить точное дерево вызовов, вызвавшее их распределение: внутри конструктора этого класса выделите объект исключения, не бросая его, получите трассировку стека исключения и сохранить его. Если позже вы обнаружите, что этот объект просочился, у вас есть необходимая трассировка стека. Просто не делайте этого со слишком большим количеством объектов, потому что выделение исключения и получение трассировки стека из него смехотворно медленны, только Microsoft знает почему.

Ответ 4

Вы можете попробовать бесплатный профайлер памяти Memoscope

https://github.com/fremag/MemoScope.Net

Я не согласен с тем, что вы можете доверять диспетчеру задач, чтобы проверить, есть ли у вас утечка памяти или нет. Проблема с сборщиком мусора заключается в том, что он может решить на основе эвристики, чтобы сохранить память после всплеска памяти и не возвращать ее в ОС. У вас может быть размер Commit размером 2 ГБ, но 90% из них могут быть бесплатными.

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

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

Ответ 5

Если вы не имеете дело с неуправляемым кодом, я бы смел сказать, что вам не нужно беспокоиться о утечке памяти. Любой объект без ссылок в управляемом коде будет удален сборщиком мусора, и возможность обнаружения утечки памяти в рамках .net я бы сказал, что вам следует считать очень удачным (ну, несчастливым). Вам не нужно беспокоиться о утечке памяти.

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

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

Если вы хотите получить более подробное представление об использовании управляемой памяти, вы можете скачать этот процесс здесь, разработанный Microsoft. Он по-прежнему довольно тупой, но он дает несколько лучший статистический вид, чем диспетчер задач.

Ответ 6

Я бы не сказал, что сборщик мусора непогрешим. Бывают случаи, когда они не понимают, и они не так прямолинейны. Потоки памяти - общая причина утечек памяти. Вы можете открыть их в одном контексте, и они могут даже не закрыться, даже если использование завершено в операторе using (определение одноразового объекта, которое должно быть очищено сразу после его использования, выходит за рамки). Если вы столкнулись с аварийными ситуациями из-за нехватки памяти, Windows создает файлы дампа, которые вы можете просеять.

введите ссылку здесь

Это отнюдь не весело или легко и довольно утомительно, но это, как правило, лучший выбор.

Общими областями, которые легко создавать утечки памяти, являются все, что использует dll System.Drawing, потоки памяти и если вы делаете серьезную многопоточность.

Ответ 7

Если вы используете Entity Framework и шаблон DI, возможно, используя Castle Windsor, вы можете легко получить утечки памяти.

Главное, что нужно сделать, это использовать инструкцию using() {}, где бы вы могли автоматически отмечать объекты как удаленные.

Кроме того, вы хотите отключить автоматическое отслеживание на платформе Entity Framework, где вы читаете и не пишете. Лучше всего изолировать свои записи, используйте с помощью функции() {} в этот момент, получите dbContext (с отслеживанием), напишите свои данные.

Если вы хотите исследовать, что находится в куче. Лучшим инструментом, который я использовал, является RedGate ANTS http://www.red-gate.com/products/dotnet-development/ants-memory-profiler/solving-memory-problems/getting-started не дешево, но он работает.

Однако, используя шаблон using() {}, где бы вы ни были (не делайте статический или однострочный DbContext и никогда не используйте один контекст в массивном цикле обновлений, избавляйтесь от них так часто, как можете!), то вы обнаружите, что память не часто является проблемой.

Надеюсь, что это поможет.