JavaRush /Java блог /Random /Кофе-брейк #210. Все типы сборщиков мусора в Java, о кото...

Кофе-брейк #210. Все типы сборщиков мусора в Java, о которых вы должны знать

Статья из группы Random
Источник: Hackernoon Благодаря этой публикации вы узнаете сильные и слабые стороны каждого типа сборщиков мусора, которые используются в Java-разработке. Кофе-брейк #210. Все типы сборщиков мусора в Java, о которых вы должны знать - 1Вопрос о сборщиках мусора (Garbage Collector, GC) можно услышать почти в каждом собеседовании. Поэтому я решил собрать всю необходимую информацию о них, используя свой любимый принцип — кратко и просто. Для начала давайте начнем с цели CG и почему нам нужны несколько типов сборщиков мусора. В таких языках, как C, нам нужно хранить информацию об объектах в памяти и писать много шаблонного кода, чтобы освободить эту память. Разумеется, утечки памяти — частые гости в таких программах. Java решает проблему утечек памяти с помощью сборщика мусора. И вы, как разработчик, должны знать, какой сборщик мусора лучше всего использовать. Многое зависит от того, где и как работает ваша программа. Она может работать на слабом оборудовании или с большим количеством объектов, или ваша программа должна быть очень быстрой. Исходя из этих условий вы должны настроить свой сборщик мусора для достижения желаемой производительности. Итак, начнем.

Как JVM работает с памятью

Виртуальная машина Java (JVM) делит память на две области: куча, в которой хранятся данные приложения, и некуча (non-heap), в которой хранится программный код и другие данные. Обратим внимание на область кучи. Именно здесь наша программа создает новые объекты. Все сборщики мусора основаны с учетом того фактора, что многие программы используют недолговечные объекты. То есть, эти объекты были созданы, затем выполнили свою функцию и больше не нужны. Таких объектов большинство. Но некоторые объекты живут гораздо дольше, возможно, даже все время существования программы. Вот тут-то и возникает идея деления объектов на молодое и старое поколение. И нам нужно очень часто проверять молодое поколение. Дело в том, что процессы уборки мусора делятся на минорную чистку, которая затрагивает только младшее поколение, и полную чистку, которая может затрагивать оба поколения. Помните, что сборщик мусора — это программа. И для ее работы требуется время и ресурсы вашего компьютера. Что также влияет на наше приложение. Как влияет? Например, чтобы выполнить сборку мусора, JVM приостанавливает наше приложение. Это называется паузой Stop-The-World (STW). В это время все потоки приложений приостановлены. Но приложение внутри об этом совершенно не подозревает. Для приложения время течет равномерно. Почему это так плохо? Вот представьте, вы пишете какое-то приложение для обмена или приложение для автопилота самолета. Ваше приложение может “заснуть” на одну секунду, и суть вашей проблемы может резко измениться. То есть, пауза является значимым параметром для каждого сборщика мусора. Следующее фундаментальное свойство сборщика мусора — это общее время, затраченное на сборку мусора, по отношению к общему времени выполнения программы. Что это значит и почему это так важно? Вместо одной большой фазы “останови мир” (Stop-The-World) мы можем выбрать алгоритм со множеством маленьких пауз. Небольшие паузы предпочтительнее, но ничего не бывает бесплатно. В этом случае мы платим увеличением общего времени выполнения программы. И мы тоже должны это учитывать. Следующий параметр — это количество аппаратных ресурсов. Каждому сборщику нужна память для хранения информации об объектах и ​​процессор для выполнения очистки. Последний параметр — скорость. Оперативность сборки мусора означает, насколько быстро и эффективно сборщик мусора (GC) освобождает память, которая больше не используется программой. Все эти параметры влияют на алгоритм, который может максимально быстро освобождать память при минимальном потреблении ресурсов. Давайте взглянем на доступные нам сборщики мусора. Для интервью вам нужно знать первые пять. Два других намного сложнее.

Serial GC

Serial GC — это сборщик мусора в виртуальной машине Java, который использовался с самого начала существования Java. Он полезен для программ с маленькой кучей и работающих на менее мощных машинах. Этот сборщик мусора делит кучу на регионы, куда входят Eden и Survivor. Регион Eden — это пул, из которого изначально выделяется память для большинства объектов. Survivor — это пул, содержащий объекты, пережившие сборку мусора в регионе Eden. По мере заполнения кучи объекты перемещаются между регионами Eden и Survivor. JVM постоянно отслеживает перемещение объектов в регионы Survivor и выбирает подходящий порог количества таких перемещений, после чего объекты перемещаются в регион старшего поколения (Tenured). Когда в регионе Tenured не хватает места, в дело вступает полная сборка мусора, работающая с объектами обоих поколений. Основным преимуществом этого сборщика мусора являются его низкие требования к ресурсам, поэтому для выполнения сборки тут достаточно маломощного процессора. Главным недостатком Serial GC являются длительные паузы при сборке мусора, особенно если речь идет о больших объемах данных.

Parallel CG

Параллельный сборщик мусора (Parallel CG) похож на последовательный конструктор. Он включает параллельную обработку некоторых задач и возможность автоматической настройки параметров производительности. Parallel GC — это сборщик мусора в виртуальной машине Java, основанный на идеях Serial GC, но с добавлением параллелизма и интеллекта. Если компьютер имеет более одного ядра процессора, старая версия JVM автоматически выбирает Parallel GC. Куча здесь разделена на те же регионы, что и в Serial GC — Eden, Survivor 0, Survivor 1 и Old Gen (Tenured). Однако в сборке мусора параллельно участвуют несколько потоков, и сборщик может подстраиваться под требуемые параметры производительности. У каждого потока-коллектора есть область памяти, которую нужно очистить. Parallel GC также имеет настройки, направленные на достижение требуемой эффективности сборки мусора. Сборщик использует статистику предыдущих сборок мусора для настройки параметров производительности в будущих сборках. Parallel GC обеспечивает автоматическую настройку параметров производительности и меньшее время паузы для сборки, но есть один незначительный недостаток в виде некоторой фрагментации памяти. Он подходит для большинства приложений, но для более сложных программ лучше выбрать более расширенные реализации сборщиков мусора. Плюсы: Во многих случаях быстрее, чем Serial GC. Имеет хорошую скорость работы. Минусы: потребляет больше ресурсов, и паузы могут быть довольно длинными, но мы мы можем настроить максимальную длительность паузы Stop-The-World.

Concurrent Mark Sweep

Сборщик мусора Concurrent Mark Sweep (CMS) направлен на уменьшение максимальной длительности пауз за счет выполнения некоторых задач по сбору мусора одновременно с потоками приложения. Этот сборщик мусора подходит для управления большими объемами данных в памяти. Concurrent Mark Sweep (CMS) — это альтернатива Parallel GC в виртуальной машине Java (JVM). Он предназначен для приложений, где требуется доступ к нескольким ядрам процессора и которые чувствительны к паузам Stop-The-World. CMS выполняет этапы сборки мусора параллельно с основной программой, что позволяет ей работать без остановки. Он использует ту же организацию памяти, что и сборщики Serial и Parallel, но не ждет заполнения области Tenured перед запуском чистки старого поколения. Вместо этого он работает в фоновом режиме и пытается сохранить компактность региона Tenured. Concurrent Mark Sweep начинается с начальной фазы маркировки, которая ненадолго останавливает основные потоки приложения и помечает все объекты, доступные из root. Затем основные потоки приложения возобновляют работу, и CMS начинает поиск всех активных объектов, доступных по ссылкам из отмеченных root-объектов. После маркировки всех живых объектов сборщик в несколько параллельных потоков очищает память от мертвых объектов. Одним из преимуществ CMS является его направленность на минимизацию времени простоя, что имеет решающее значение для многих приложений. Однако он требует жертвы в виде ресурсов процессора и общей пропускной способностью. Кроме того, CMS не сжимает объекты в старом поколении, что приводит к фрагментации. Долгие паузы из-за возможных сбоев параллельного режима могут стать неприятным сюрпризом (хотя они случаются нечасто). При наличии достаточного количества памяти CMS удается избежать таких пауз. Плюсы: Быстрый. Имеет небольшие паузы Stop-The-World. Минусы: потребляет больше памяти, при недостатке памяти некоторые паузы могут быть длинными. Не очень хорош, если приложение создает много объектов.

Garbage-First

Garbage-First (G1) считается альтернативой CMS, особенно для серверных приложений, работающих на многопроцессорных серверах и управляющих большими наборами данных. Сборщик мусора G1 преобразует память в несколько регионов одинакового размера, за исключением огромных регионов (которые создаются путем слияния обычных регионов для размещения массивных объектов). Регионы не обязательно должны быть организованы в ряд и могут менять принадлежность к своему поколению. Небольшие чистки выполняются периодически для младшего поколения и перемещения объектов в регионы Survivor или апгрейда их до старшего поколения с переводом в Tenured. Очистка выполняется только в тех регионах, где нужно избежать превышения желаемого времени. Сборщик сам прогнозирует и выбирает для очистки регионы с наибольшим количеством мусора. Полная очистка используют цикл маркировки для создания списка живых объектов, который работает параллельно с основным приложением. После цикла маркировки G1 переключается на запуск смешанных чисток, которые добавляют регионы старшего поколения к набору регионов младшего поколения, подлежащих очистке. Сборщик мусора G1 считается более точным, чем сборщик CMS, в прогнозировании размеров пауз и лучше распределяет сбор мусора во времени, чтобы предотвратить длительные простои приложений, особенно при больших размерах кучи. Он также не фрагментирует память, как сборщик CMS. Однако сборщику G1 требуется больше ресурсов процессора для работы параллельно с основной программой, что снижает пропускную способность приложения. Плюсы: работает лучше, чем CMS. Имеет более короткие паузы. Минусы: потребляет больше ресурсов процессора. Также он потребляет больше памяти, если у нас много довольно больших объектов (более 500 КБ), потому что он помещает такие объекты в один регион (1-32 МБ).

Epsilon GC

Epsilon GC разработан для ситуаций, когда сборка мусора не требуется. Он не выполняет сборку мусора, а использует TLAB (thread-local allocation buffers, локальные буферы выделения потока) для выделения новых объектов — небольших буферов памяти, запрашиваемых отдельными потоками из кучи. Огромные объекты, не помещающиеся в буфер, запрашивают блоки памяти специально для себя. Когда Epsilon GC исчерпывает ресурсы, генерируется ошибка OutOfMemoryError, и процесс завершается. К преимуществам Epsilon GC относятся меньшие требования к ресурсам и более быстрое выделение памяти для приложений, которые создают все необходимые им объекты при запуске или запускают недолговечные приложения, не использующие всю выделенную память. Epsilon GC также может помочь проанализировать требования к ресурсам, которые другие сборщики мусора добавляют в ваше приложение. Достоинства: Очень быстрый. Минусы: не очищает объекты :) Следующие два коллектора являются самыми передовыми в своем роде, но также самыми сложными. Поэтому рассмотрим их кратко.

ZGC

ZGC может поддерживать паузы на уровне менее миллисекунды даже при работе с огромными объемами данных. ZGC — это сборщик мусора, разработанный Oracle для Java, который предназначен для обеспечения высокой пропускной способности и низкой задержки при обработке больших куч (до 16 ТБ). ZGC основан на принципах виртуальной памяти и использует разные цвета маркировки для отслеживания состояния объектов во время сборки мусора. Плюсы: паузы менее миллисекунды, даже в больших кучах, что очень полезно для приложений, требующих короткого времени обработки запросов. Он работает с очень большими кучами с хорошей пропускной способностью. ZGC может сжимать динамическую память во время сборки мусора. Минусы: Высокая загрузка процессоров и ощутимые требования к производительности, что может замедлить время запуска приложений.

Shenandoah GC

Shenandoah GC — еще один сборщик мусора с короткими паузами независимо от размера кучи. Этот сборщик мусора разработан компанией Red Hat. Он предназначен для минимизации времени, затрачиваемого приложением на сборку мусора. Как и ZGC, это параллельный сборщик, что означает, что он работает во время работы приложения, сводя к минимуму паузы. Shenandoah GC использует “указатели пересылки” для перемещения объектов во время сборки мусора. Также он имеет метод под названием “устранение барьера нагрузки” для повышения производительности. Плюсы: Shenandoah GC может достичь короткого времени паузы, часто менее 10 мс, даже для массивных куч. Хорошая пропускная способность. Минусы: высокая загрузка процессора и сложность в работе при больших нагрузках.

Заключение

Сборщики мусора — одна из самых сложных задач в программировании. В этом направлении постоянно ведутся новые разработки. И хотя программисты очень редко прибегают к настройке GC, вам все же необходимо хотя бы поверхностно знать, как работает ваш инструмент сборки мусора.
Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Oraz Janov Уровень 34
2 апреля 2023
Спасибо. Было познавательно