Re: Профайлер показывает Garbage Collection
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 20.01.17 17:50
Оценка: 151 (9)
Здравствуйте, vladpol, Вы писали:

V>Пытаясь улучшить производительность и найти узкие места, натравливаю на приложение профайлер. И нашел несколько "долгих" методов где до 80% занимает "Garbage Collection". Но на вид ничего военного. Как правильно копать дальше,


Проблема с профилированием GC в том, что она сборка мусора недетерминирована. Тут легко получить эффект бабочки. Вот пример: приложение выделяет много памяти в методе M1, но при этом не достаточно много, чтобы затриггерить долгую сборку мусора второго поколения. Потом вызывается метод М2, который выделят небольшой объект, но именно из-за него триггерится сборка второго поколения и профайлер показывает, что M2 тормоз и 80% отнимает GC.

Если GC влияет на производительность, то я обычно предпринимаю следующие шаги:

1. Выяснить, сколько именно времени занимает сборка мусора в процентном отношении ко времени работы приложения.
Качаем PerfView, запускаем его с включенной галочкой GC Collect Only на вкладке Collect. Это можно делать даже на проде, если нужно, поскольку подобный анализ очень и очень легковесный.
Запускаем сбор данных (кнопка Start Collection) и стартуем приложение. Через некоторое время (хз, что за приложение) нужно найти устойчивое состояние приложение, когда оно сделало работу или насосало достаточно данных для анализа.
Открываем отчет в PerfView и смотрим процент времени, которое отнимает GC от времени работы приложения.
Если значение сильно больше 10%, то, "Хьюстон, у нас проблемы" (с).

2. Если первый пункт показал, что у нас проблемы с памятью, то их нужно решать.
Тут все несколько сложнее, чем может показаться на первый взгляд.
GC — умный, но есть варианты. Первое, что нужно глянуть — это режим работы сборки мусора — Server GC vs. Workstation GC. Если на запускаемых машинах нет проблемы с памятью, а приложение — это некоторая форма числодробилки, батч-процесса, сервиса, то можно переключиться на Server GC с дефолтного Workstation GC. Может здорово помочь, поскольку сборка мусора будет менее агрессивной.

Затем думаем, как сделать приложению резекцию.
Я делал следующее: с помощью PerfView или с помощью более мощной тулы (я использовал .NET Memory Profiler от memprofiler.com) смотрим, кто жрет место.
Обычно можно найти группу объектов, которых сотни тысяч или даже миллионы, часть полей которых вообще-то не нужна. В этом случае, редко используемые поля выносятся в другие классы, чтобы разделить 'hot path', от 'corner case'-ов.
Так же смотрим, нет ли каких-то глупых и ненужных аллокаций: обилие строк — это нормально, но если их сильно много, то возможно есть проблемы с чрезмерным использованием конкатенации строк вручную. Опять же, могут быть аллокации делегатов: недавно, замена Method Group делегата, на лямбду помогло срезать пару процентов end-2-end времени исполнения, поскольку первые никогда не кэшируются, а создание делегата оказалось на очень горячем пути работы приложения.

Да, и тот же PerfView покажет, в чем причина триггеринга сборки мусора. Это даст понять, например, виновато ли приложение. Вполне возможно, что сборка мусора триггерится из-за нехватки памяти в системе, и нужно просто сделать резекцию винде и убрать кучу ненужных сервисов. Это маловероятно, но возможно. Профейлер памяти так же сможет показать, кто источник мусора, а также какой процент составляет мусор при каждой сборке. Вполне возможный вариант, что в приложении mid life crysis, когда короткоживущие объекты не убиваются при первой и второй сборках, а переходят во второе поколение, сборка которого является дорогой. Поэтому нужно обратить внимание в отчете PerfView на количество сборок мусора в разных поколениях и на среднее время каждой сборки. Это также поможет понять, что же происходит внутри приложения.

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