Утечка памяти в приложении.net + странное поведение GC
Я не был полностью уверен, куда обратиться за помощью с этим, поэтому я решил попробовать stackru, так как он обычно дает ответы примерно на 90% всех моих вопросов, связанных с программированием.
Короче говоря, у меня есть приложение с открытым исходным кодом.NET, которое утечка памяти. Это не может быть настоящей утечкой памяти в том смысле, что, когда приложение закрывается, я подозреваю, что память освобождается, но во время работы она постоянно выделяет больше памяти, не освобождая ее. В конце концов, System.OutOfMemoryException
брошен
Чтобы устранить проблему, я выполнил шаги, рекомендованные в этой статье, и создал следующий график, где красный - это память.NET/CLR "#Bytes in all Heaps", а зеленый - это процесс "Private Bytes" с инструментом Windows Performance Monitor. (Обратите внимание, что зеленая линия была равномерно уменьшена, чтобы оказаться ближе к красной линии, так как для меня важны только формы линий): Выход монитора производительности.
Я взял это изображение как доказательство управляемой утечки памяти и добавил инструмент диагностики отладки Windows, чтобы попытаться найти источник утечки (как упомянуто в статье). Однако отчет, который я получил от Debug Diagnostic Tool, очень необычен.
По сути, каждая попытка собрать "Full UserDump", которую я пытался выполнить каждые 5 секунд во время работы приложения, была сорвана тем фактом, что сборщик мусора всегда находился в середине цикла сбора мусора в то время, что вызывало диагностику отладки. Инструмент для вывода ошибки и предотвращения сбора полезной информации о памяти.NET.
Теперь я застрял, я знаю, что у меня есть управляемая утечка памяти, но я не знаю, как сузить, где это. Я также смущен тем, как сборщик мусора всегда находился в середине цикла сбора, и меня интересует, был ли каким-то образом заблокирован поток сбора мусора, не позволяющий освободить память и / или выйти из цикла сбора мусора.
В некоторых разделах Графика системного монитора производительность выделенной памяти.NET немного уменьшается, поэтому сборщик мусора не зависал вечно, но это должно было происходить большую часть времени, в противном случае диагностика отладки должна была бы справиться с этим. UserDump.
Пара вопросов:
Может ли сборщик мусора в приложении.NET застрять при попытке освободить часть памяти, возможно, из-за плохо закодированного деструктора / финализатора или чего-то еще?
Какую стратегию я могу использовать, чтобы продолжить сужать источник проблемы?
1 ответ
Было бы полезно, если бы вы указали версию.NET Framework, версию ОС, скорость вашего процесса и количество процессоров на вашем компьютере. Если вы очень скоро получите исключение "Недостаточно памяти", это заставит меня подумать, что вы запускаете 32-битный процесс, но все равно поможет, если вы сможете подтвердить.
Прежде всего вы должны проверить, действительно ли GC является причиной проблемы, посмотрев счетчик % времени в памяти GC для вашего процесса. Вы можете контролировать это в PERFMON под объектом.NET CLR Memory. Если этот счетчик> 30%, то наверняка у вас есть проблемы с ГХ. Вставленный вами PNG не говорит мне, сколько памяти в секунду выделяется, поэтому, если он высокий, то GC увеличит его.
Одним из предостережений было бы использование новейшего средства диагностики отладки для анализа дампа и проверки того, видите ли вы что-то другое. В Debug Diag 1.2 существует проблема, которая может привести к тому, что сообщение "середина сборки мусора" будет сообщено неверно, поэтому вы хотите убедиться, что GC действительно работает во время дампа или нет. Вы можете скачать последнюю версию с http://www.microsoft.com/en-us/download/details.aspx?id=40336 и проанализируйте один и тот же файл дампа с помощью инструмента и посмотрите, сообщает ли это что-то другое. Также поищите в своем отчете строку GarbageCollectionGeneration, и она покажет вам ветку, которая отвечала за вызов GC. Глядя на стек этого потока, вы сможете определить, что этот поток делал, что в конечном итоге вызывает GC. Это может или не может помочь.
Отвечая на другие ваши вопросы: -
1) GC может застрять, если в каком-либо потоке предварительно отключен GC. Вы можете прочитать статью http://blogs.msdn.com/b/tess/archive/2008/02/11/hang-caused-by-gc-xml-deadlock.aspx чтобы узнать больше о PRE-EMPTIVE GC и о том, как выяснить темы, для которых отключен приоритетный сборщик мусора.
2) Я бы открыл дамп в WinDBG и увидел бы, следуйте подходу, упомянутому в приведенном выше блоге, чтобы увидеть, достигну ли я чего-нибудь. Если платформа представляет собой.net Framework 4.0 или выше, вы также можете использовать инструмент PERFVIEW для сбора трассировки, и это дает хорошую информацию о том, почему происходит сборщик мусора. Посмотрите видео о PERFVIEW для решения проблемы GC по адресу http://channel9.msdn.com/Series/PerfView-Tutorial/PerfView-Tutorial-9-NET-Memory-Investigation-Basics-of-GC-Heap-Snapshots
Также, если этот EXE-файл выполняет некоторую фоновую обработку, вы можете включить режим сервера GC и посмотреть, поможет ли это. Прочитайте статью http://blogs.msdn.com/b/clyon/archive/2004/09/08/226981.aspx для получения дополнительной информации о том же.
надеюсь это поможет!!!