Профайлер показывает Garbage Collection
От: vladpol Украина http://vlad-mislitel.livejournal.com/
Дата: 20.01.17 17:13
Оценка:
Пытаясь улучшить производительность и найти узкие места, натравливаю на приложение профайлер. И нашел несколько "долгих" методов где до 80% занимает "Garbage Collection". Но на вид ничего военного. Как правильно копать дальше,
С уважением, Владислав Полищук
Отредактировано 21.01.2017 9:52 AndrewVK . Предыдущая версия .
gc profiler
Re: Профайлер показывает Garbage Collection
От: nikov США http://www.linkedin.com/in/nikov
Дата: 20.01.17 17:42
Оценка: +2
Здравствуйте, vladpol, Вы писали:

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


Смотреть memory профайлером, какие объекты создаются.
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 на количество сборок мусора в разных поколениях и на среднее время каждой сборки. Это также поможет понять, что же происходит внутри приложения.

З.Ы. надеюсь, что что-то из этого поможет и я с радостью помогу с дальнейшим исследованием, как только ты сможешь выложить результаты профилирования (если такое возможно).
Re[2]: Профайлер показывает Garbage Collection
От: Sinix  
Дата: 21.01.17 07:12
Оценка: 40 (3)
Здравствуйте, SergeyT., Вы писали:

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

ST>Я делал следующее: с помощью PerfView или с помощью более мощной тулы (я использовал .NET Memory Profiler от memprofiler.com) смотрим, кто жрет место.

Хм, я обычно иду с другой стороны — смотрю аллокации. Вместе с heap allocations viewer для решарпера прям отлично работает. DotMemory точно умеет, вот как оно выглядит. И студийный профайлер вроде тоже научился.

Разбор по статическому снимку хорош для поиска утечек, но никак не избыточных аллокаций, как правило, именно они являются основной причиной частых GC.
Re[3]: Профайлер показывает Garbage Collection
От: fddima  
Дата: 22.01.17 03:18
Оценка: 55 (3)
Здравствуйте, Sinix, Вы писали:

И в дополнение к вам обоим: особенно на сервере/сервисах — я беру первым делом Process Hacker 2 (в отличие от Process Explorer) который без гемороя показывает .net performance counters и в разделе Memory смотрю на процент времени GC, количество сборок и размеры хипов. А так же остальные самые интересные разделы по вкусу (Threads например).
После чего если очень интересно кто (объекты каких типов, где спят потоки и т.п.) жрёт память — полный дамп памяти (всё тем же process hacker), затем windbg+sos. Дешево и сердито. Правда я практиковал именно такое, т.к. зачастую более суток надо, что-бы проблема начала проявляться.

PS: И в итоге, обнаружил как-то что клиентская либа толи к ксандре толи ещё к чему использует BlockingCollection в своём же Async методе. В итоге — какими-то чудесами почти все потоки пула — спят именно тут (потому что узел кластера по сети не доступен, но либа не видит что он уже поднялся и пора работать), а другие потоки наваливают работы в тред пул (посредством Task.Run). Но... голодания как-бы не происходит. В итоге жуткий перерасход памяти и 0 работы, на фоне нулевой загрузки ЦП.
Re[4]: PH2 vs PE
От: Sharov Россия  
Дата: 23.01.17 11:47
Оценка:
Здравствуйте, fddima, Вы писали:

F>Здравствуйте, Sinix, Вы писали:


F> И в дополнение к вам обоим: особенно на сервере/сервисах — я беру первым делом Process Hacker 2 (в отличие от Process Explorer) который без гемороя показывает .net performance counters и в разделе Memory смотрю на процент времени GC, количество сборок и размеры хипов. А так же остальные самые интересные разделы по вкусу (Threads например).

F> После чего если очень интересно кто (объекты каких типов, где спят потоки и т.п.) жрёт память — полный дамп памяти (всё тем же process hacker), затем windbg+sos. Дешево и сердито. Правда я практиковал именно такое, т.к. зачастую более суток надо, что-бы проблема начала проявляться.

PE может делать все тоже самое, в чем разница непонятно
Кодом людям нужно помогать!
Re[5]: PH2 vs PE
От: fddima  
Дата: 23.01.17 13:48
Оценка:
Здравствуйте, Sharov, Вы писали:

S>PE может делать все тоже самое, в чем разница непонятно

Я же писал в посте выше: PE часто просто не вычитывает перформанс кантеры, хотя должен.
Re[6]: PH2 vs PE
От: Sharov Россия  
Дата: 23.01.17 13:58
Оценка:
Здравствуйте, fddima, Вы писали:

F>Здравствуйте, Sharov, Вы писали:


S>>PE может делать все тоже самое, в чем разница непонятно

F> Я же писал в посте выше: PE часто просто не вычитывает перформанс кантеры, хотя должен.

Ни разу не сталкивался с ситуацией, когда PE что-то там не вычитывает для дотнет приложения. Такое вообще может быть?
Кодом людям нужно помогать!
Re[7]: PH2 vs PE
От: fddima  
Дата: 23.01.17 14:08
Оценка: 6 (1)
Здравствуйте, Sharov, Вы писали:

S>Ни разу не сталкивался с ситуацией, когда PE что-то там не вычитывает для дотнет приложения. Такое вообще может быть?

В апреле 2016 я брал свежий PE и опять наблюдал эту картинку. Это на сервере. На моей локальной тачке — он почти всегда работал. (*)
Как такое может быь — интересно не было, при наличие иного, на мой взгляд более удобного инструмента.

(*) Имхо — там что-то с правами, а точнее комбинация прав и юзеров, при том что ты админ — не важно. Я такое поведение наблюдал почти с самого начала.
Re[8]: PH2 vs PE
От: Sharov Россия  
Дата: 23.01.17 15:15
Оценка:
Здравствуйте, fddima, Вы писали:

F>Здравствуйте, Sharov, Вы писали:


S>>Ни разу не сталкивался с ситуацией, когда PE что-то там не вычитывает для дотнет приложения. Такое вообще может быть?

F> В апреле 2016 я брал свежий PE и опять наблюдал эту картинку. Это на сервере. На моей локальной тачке — он почти всегда работал. (*)
F> Как такое может быь — интересно не было, при наличие иного, на мой взгляд более удобного инструмента.

Интересно, если PE не работал, то как PH работал? Я бы в случае отказа PE взял бы Perf. Monitor -- возни побольше, но как-то гибче и интерактивнее.
Кодом людям нужно помогать!
Re[2]: Профайлер показывает Garbage Collection
От: IT Россия linq2db.com
Дата: 23.01.17 16:30
Оценка: +1
Здравствуйте, SergeyT., Вы писали:

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


И про GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; не забываем, если в наличии интенсивная работа с большими объектами.
Если нам не помогут, то мы тоже никого не пощадим.
Re[3]: Профайлер показывает Garbage Collection
От: Sinix  
Дата: 23.01.17 16:44
Оценка:
Здравствуйте, IT, Вы писали:

IT>И про GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; не забываем, если в наличии интенсивная работа с большими объектами.


+1 кстати.
Оффтоп: чтоб не потерялось: глянь вот эту ветку
Автор: Sinix
Дата: 19.01.17
про ComparerBuilder<T> как будет время, ок?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.