Страницы

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

воскресенье, 15 декабря 2019 г.

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

#c_sharp #net #оптимизация #производительность #сборщик_мусора


Сделал дамп памяти своего сетевого асинхронного приложения и прошелся по нему такой
замечательной утилитой, как 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. приводить какой либо пример кода нерационально, приложение большое, много кода.
    


Ответы

Ответ 1



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

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

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