Страницы

Поиск по вопросам

четверг, 25 октября 2018 г.

Борьба с GC, из-за которого другие потоки блокируются

Сделал дамп памяти своего сетевого асинхронного приложения и прошелся по нему такой замечательной утилитой, как DebugDiag 2 Analysis от Microsoft. Она выдала ошибку и предупреждение, вот их содержание:

Error:
In NetworkApplication.DMP GC is running in this process. The Thread that triggered the GC is 330.
Warning:
This thread is waiting for .net garbage collection to finish. Thread 330 triggered the garbage collection. The gargage collector thread wont start doing its work till the time the threads which have pre-emptive GC disabled have finished executing. The following threads have pre-emptive GC disabled 330. 89,45% of threads blocked (534 threads).

Рекомендации по исправлению, которые дала тулза:
Error:
When a GC is running the .NET objects are not in a valid state and the reported analysis may be inaccurate. Also, the thread that triggered the Garbage collection may or may not be a problematic thread. Too many garbage collections in a process are bad for the performance of the application. Too many GC's in a process may indicate a memory pressure or symptoms of fragmenation. Review the blog ASP.NET Case Study: High CPU in GC - Large objects and high allocation rates for more details.
Warning:
Review the callstacks for the threads that have preemptive GC Disabled to see what they are doing which is preventing the GC to run. Review the blog .NET Hang Case Study: The GC-Loader Lock Deadlock (a story of mixed mode dlls) that gives some information on how to debug these issue more.

Соответственно приложение асинхронное и работает на потоках ThreadPool с дефолтными настройками. Версия .NET: 4.6.2 x64, перевел для более оптимальной работы RyuJIT, который в первых версиях работал не очень хорошо. Может быть это даже и плюс, потому что в этой версии фреймворка доступны новые методы управления сборщиком мусора. ОC: Windows Server 2012 r2 x64
Вопрос: Вообще с GC возможно как то бороться в данном случае (когда он начинает "втыкать" не по детски)? Что нужно оптимизировать? Какие советы можете дать или как лично боролись с подобными проблемами (тоже интересно почерпнуть чужой опыт).
p.s. приводить какой либо пример кода нерационально, приложение большое, много кода.


Ответ

ИМХО, бороться с GC не надо. Надо стараться избегать лишнего, неоправданного memory traffic'а. Тема нетривиальная, но можно выделить два основных совета:
Избегать ненужного "старения" объектов (переходов из Gen0 -> Gen1 -> Gen2); Избегать частого создания/пересоздания объектов, попадающих в LOH (Large object heap, туда попадают объекты размером более 85000 байт).
P.S.: Попробуйте проанализировать дамп вашего процесса при помощи утилиты WinDBG при помощи команды !DumpHeap -stat (подробнее можно почитать на MSDN). Посмотрите объектов какого типа подозрительно много, проанализируйте историю создания этих объектов (команда GCRoot).

Комментариев нет:

Отправить комментарий