Сборщик мусора(garbage collector) - компонент JVM, который размещает объекты в памяти. Выделяет место под новые и определяет те, которые уже не нужны.
В java есть 5 типов сборщика мусора - Serial Collector, Parallel Collector, Concurrent Mark Sweep (CMS), Garbage-First (G1) и Z Garbage Collector(ZGC). В java 8 вариантом по умолчанию является Parallel GC, в java 9 это G1. ZGC - самый новый, он появился в java 11.
Эффективность GC оценивается по следующим параметрам:
▪️Latency — сколько времени занимает сборка мусора. Измеряется в миллисекундах.
▪️Throughput — как часто она происходит. Пропускная способность считается в процентах времени VM и рассчитывается как обратная величина. Если сборка мусора занимает 5% времени,то throughput равен 95%.
▪️Footprint — сколько ресурсов использует GC. Учитывается количество памяти для корректной работы.
Достичь хороших значений во всех трёх показателях невозможно. Для разных GC в приоритете будут разные параметры, но для каждого доступно множество опций для изменений под требования системы.
Основной принцип работы сборщика мусора — разделение объектов по поколениям.
▫️Недавно созданные объекты относятся к «молодым». Промежуточные объекты, итераторы, локальные переменные - самые вероятные кандидаты на удаление. На них сфокусирована основная часть внимания GC. Ещё они делятся на 2 подгруппы: только что созданные и выжившие после нескольких сборок мусора.
▫️Если объект пережил много циклов работы GC (по умолчанию 15), то он переходит в «старое» поколение и проверяется реже.
Деление на поколения не абстрактное. Если объект переходит в другое поколение, он физически меняет своё место в памяти, и все ссылки на него обновляются.
В ранних версиях сборщиков мусора память делилась на 4 региона:
🟥 Eden — здесь создавались новые объекты.
🟧 Survivor – для переживших несколько сборок мусора.
🟪 Tenured – для долгоживущих объектов.
🟦 Permanent – метаинформация JVM о классах, методах и тд.
Выглядело всё примерно так:
🟥🟥🟥🟥🟥🟥🟧🟧🟧🟪🟪🟦
В G1 область Permanent удалена, а метаинформация перенесена в отдельную часть памяти под названием Metaspace.
Второе изменение — память разделилась на 2000 регионов одного размера, по умолчанию 1МБ. Тип региона может меняться. Для больших объектов регионы объединяются.
Стало как-то так:
🟥🟪🟧🟧🟥🟪🟥🟥🟧🟪
Плюсы и минусы G1:
✅ Выборочная обработка группы регионов – получаем высокий latency.
✅ Предсказуемое время обработки.
✅ Сборка мусора в основном выполняется параллельно с работой приложения.
✅ Нет проблем с фрагментацией.
➖ Затраты на поддержку такой системы чуть снижают throughput.
Целевое значение пропускной способности для G1 - 90%. Для Parallel GC это значение равно 99%.
➖ Плохо работает с heap меньше 6Гб.
Чтобы проанализировать и оптимизировать работу G1, в первую очередь нужно включить логгирование, а уже затем экспериментировать с флажками JVM.
-
Xloggc:/path/to/gc.log
-XX:+PrintGCDetails
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintGCApplicationConcurrentTime Но вообще G1 адаптируется к нагрузке и прекрасно работает со значениями по умолчанию.