Приложение.NET внезапно испытывает резкий рост неуправляемой памяти
Я запускаю приложение, которое показывает некоторые очень специфические проблемы. Он работает нормально около 2,5 часов, затем внезапно начинает расти неуправляемая память и быстро расти. Примерно через полчаса приложение вылетает.
Приложение не использует неуправляемые библиотеки DLL. Это общение с внешним приложением. Он пишет с помощью сокета (используется через поток) и читает через поток WCF.
Я сделал это с помощью ANTS. Внезапное изменение в использовании неуправляемой памяти очень поразительно; он остается идеально ровным навсегда, затем внезапно начинает увеличиваться и продолжает делать это с постоянной скоростью, пока приложение не выйдет из строя. Ничто в управляемой памяти не кажется неуместным.
Учитывая, что я не намеренно использую неуправляемый код, трудно определить, откуда происходит утечка. ANTS не поможет. Трудно очистить код от проблем, когда он не увеличивается с самого начала (приложение все время бездействует, хотя оно и пингует свой сервер один раз в секунду через сокет с очень небольшим битом данных).
Чтобы повторить, приложение и сервер оба простаивают в течение этого времени; он работает в изолированной тестовой системе (как на сервере, так и на клиенте). Клиент - тот, который протекает.
2 ответа
Возможно, вы захотите использовать DebugDiag для мониторинга утечек памяти и предоставления информации о том, что было выделено, сколько и из каких стеков вызовов. Короче:
Вскоре после запуска (или перезапуска) процесса выполните следующие действия:
- Откройте DebugDiag.
- Отмена из мастера.
- Перейдите на вкладку Процессы.
- Щелкните правой кнопкой мыши по нужному процессу.
- Выберите "Монитор на утечки".
- Нажмите ОК.
После того, как процесс запущен некоторое время, и проблема с памятью очевидна:
- Перейти к DebugDiag
- Если он еще не был открыт, отмените его из мастера.
- Перейдите на вкладку Процессы.
- Щелкните правой кнопкой мыши по тому же процессу, что и часть № 1.
- Выберите Create Full Userdump.
- Запишите местоположение свалки.
Кроме того, если процесс перезапускается до захвата дампа памяти, мониторинг утечки должен быть повторно включен.
Как только у вас есть свалка:
- Перейти к DebugDiag.
- Перейдите на вкладку "Расширенный анализ".
- Выберите скрипт "MemoryAnalysis.asp" вверху.
- Нажмите "Добавить файлы данных" внизу и выберите созданный ранее дамп.
- Нажмите "Начать анализ" и просмотрите результаты.
Получив эту информацию, вы сможете определить, откуда происходит выделение памяти, и, надеюсь, причину ваших проблем.
Вы можете найти больше информации на следующих ресурсах:
В конце концов мы нашли проблему. Оказалось, что у нас было сокетное соединение между ними, и во время фазы ожидания мы отправляли пакет KeepAlive, чтобы предотвратить автоматическое отключение слушателя. Однако после некоторого времени простоя, в течение некоторого времени ожидания с WCF сокет закрывался на стороне сервера.
Таким образом, в основном каждый раз, когда запускается DispatchTimer, пакет keep-alive будет записываться в сокет, но, очевидно, он будет блокироваться. Это не помешает следующему DispatchTimer сделать то же самое. Хотя казалось, что это нечто большее, эти маленькие пакеты быстро накапливались и поглощали всю неуправляемую память, я полагаю, что буфер для сокета (я полагаю, мы использовали NetworkStream для соединения). С несколькими изменениями в логике проблема исчезла.
Спасибо за все вклад, хотя, это было высоко оценено!