Сводка по сборке мусора JVM G1

Java

Введение

В версии jdk7 появился сборщик мусора G1 (Garbage-First), особенность которого в том, что он может максимально удовлетворить требования пользователя по времени паузы при сохранении высокой пропускной способности. G1 позиционируется как замена CMS.По сравнению с CMS, G1 может более эффективно избегать фрагментации, позволяя пользователям указывать ожидаемое время паузы.

Механизм G1

G1 также является сборкой мусора поколений, но разница в том, что G1 делит всю кучу на блоки одинакового размера (называемые регионами), и каждому региону может быть назначена разная роль (молодой, райский, старый и т. означает, что объем памяти разных поколений не является фиксированным и может гибко регулироваться.

G1 определит размер региона (минимум 1M, максимум 32M) при запуске jvm.Обычно G1 пытается разделить кучу на 2048 регионов одинакового размера.От этого рассчитывается конкретный размер региона, который также может быть указан в параметры JVM. Разным регионам будут назначены разные логические роли, такие как eden/old, и разные регионы одной и той же логической роли не обязательно будут следовать друг за другом.

Механизм работы G1 аналогичен механизму CMS. G1 будет выполнять параллельную глобальную маркировку, чтобы определить, жив объект или нет. После завершения маркировки G1 может узнать, в каких регионах больше всего мусора, а затем переработать эту часть сначала регион, который является источником названия G1. G1 применяет модель прогнозирования времени паузы, чтобы максимально соответствовать заданному пользователем времени паузы, и выбирает, какие области восстанавливать в соответствии с указанным пользователем временем паузы.

G1 использует алгоритм репликации при сборке мусора, G1 скопирует оставшиеся уцелевшие объекты в каждом регионе в отдельный регион, так что сортировка памяти будет завершена в процессе утилизации. Чтобы сократить время паузы в процессе репликации, весь процесс репликации параллелен, и CMS не выполняет сортировку памяти, а ParallelOld напрямую сортирует всю кучу, что, очевидно, увеличивает время паузы.

Этапы G1

young gc

Когда возникает молодой gc, уцелевший объект копируется в оставшуюся область, и если возраст объекта превышает пороговое значение, он будет перемещен в старую область. Весь молодой процесс gc является STW, и размер области eden и области выживания в следующем GC будет пересчитан, а также в процессе расчета будет учитываться заданное пользователем целевое время паузы. Из-за дизайна регионов на самом деле очень легко изменить размер отдельных разделов.

concurrent marking cycle

Одновременный тег является важной фазой в G1. Этот этап включает в себя несколько шагов для сбора информации, такой как использование каждого региона со стороны параллельных тегов, чтобы помочь указанной пользователем время паузы.

начальная отметка (STW)

Этот шаг выполняется вместе с молодым gc.Сначала помечаются объекты, непосредственно достижимые корнями gc.

root region scanning

После молодого gc объекты в оставшемся в живых помечаются как корневая область.В это время старый регион, непосредственно доступный из оставшегося в живых региона, сканируется и помечается. Этот этап должен быть завершен до нового раунда молодых gc. Если в это время требуется молодой gc, он будет ждать завершения сканирования, прежде чем продолжить.

concurrent marking

Сканируем всю кучу, отмечаем живые объекты, вся фаза идет параллельно приложению, возможно прерывается молодым gc. На этом этапе из стека сканирования непрерывно берутся ссылки, и рекурсивно сканируется граф объектов во всей куче. Каждый раз, когда объект сканируется, он помечается, и его поля помещаются в стек сканирования. Процесс сканирования повторяется до тех пор, пока стек сканирования не станет пустым. Процесс также сканирует ссылки, записанные барьером записи SATB.

замечание (STW)

После завершения одновременной маркировки каждый поток Java все еще будет иметь некоторые ссылки на записи барьера записи SATB, которые останутся необработанными. Этот этап отвечает за обработку оставшихся ссылок. На этом этапе также выполняется обработка слабого эталона. Обратите внимание, что между этой паузой и репликой CMS есть существенная разница, то есть эта пауза требует только сканирования буфера SATB, в то время как реплика CMS требует повторного сканирования грязной карты в таблице mod-union плюс весь корневой набор, и в это время весь молодой ген (независимо от того, мертв объект или жив) будет считаться частью корневого набора, поэтому ремарка CMS может быть очень медленной.

Очистка (STW)

На этом этапе каждый регион будет очищен, а Rset заодно будет обновлен, и если есть пустой регион, то он будет освобожден.

копирование (STW)

Скопируйте уцелевшие объекты в новый регион.

Резюме G1 по переработке отходов в старости

  • параллельная стадия оценки
    • Информация о живых объектах вычисляется одновременно во время выполнения
    • На этапе репликации G1 определяет, какой приоритет региона будет переработан на основе информации о живом объекте в каждом регионе.
    • Нет процесса очистки, аналогичного тому, что используется в CMS (поскольку он напрямую очищает весь регион)
  • стадия замечания
    • Алгоритм SATB, (предположительно) будет быстрее, чем CMS
    • Пустые регионы будут восстановлены напрямую
  • этап очистки/копирования
    • Одновременно перерабатываются как молодые, так и старые участки
    • Выберите конкретный СТАРЫЙ регион региона для переработки в зависимости от ситуации

Гибридный ГХ

После полного цикла маркировки G1 преобразуется в смешанный gc на следующем молодом gc.При смешанном gc G1 может добавить часть старого региона в Cset и использовать алгоритм молодого gc для очистки части старого региона. Когда G1 восстановит достаточное количество старых регионов, он снова вернется к молодому gc, пока не завершится следующий параллельный цикл маркировки.

Суммировать

Цель G1 — заменить CMS, которая делит все пространство кучи на разные регионы для управления, делая выделение и высвобождение более гибкими. Основные действия G1 включают в себя молодой сборщик мусора, смешанный сборщик мусора и параллельную маркировку, которая решает, какие области памяти следует восстановить на основе целевого времени паузы, указанного пользователем.

Запоминаемые наборы и наборы коллекций

RSet используется для записи ссылок на регион.Каждый регион соответствует RSet.Эта структура данных записывает, какие другие регионы содержат ссылки на объекты в этом регионе. CSet записывает регионы, которые будут восстановлены в процессе GC, а уцелевшие объекты в CSet будут скопированы в новые пустые регионы в процессе GC. И Rset, и Cset являются дополнительными структурами данных, созданными для помощи в сборке мусора.

Как и другие сборщики мусора HotSpot VM, куча G1 имеет карточную таблицу, охватывающую всю кучу. Логически говоря, набор RSet G1 — это одна копия на регион. Этот RSet записывает карты, указывающие на этот регион из других регионов. Так что это своего рода «указывает на» Запоминаемый Набор. Запоминаемый набор, реализуемый карточной таблицей, обычно является указателем, то есть карточная таблица должна записать указатель на другой диапазон из диапазона, который она охватывает. Возьмем, к примеру, карточную таблицу поколенческого GC для записи межпоколенческого указателя старого -> молодого, помеченная карта находится в рамках старого поколения.

G1 добавляет слой структуры к таблице карточек точек-вне, чтобы сформировать набор точек-в-RSet: каждая область будет записывать, какие другие области имеют указатели на себя и в каких карточках находятся эти указатели в пределах диапазона. Этот RSet на самом деле является хеш-таблицей, ключ — это начальный адрес других регионов, значение — множество, а элемент в нем — индекс карточной таблицы.

Алгоритм SATB

G1 использует алгоритм SATB в фазе одновременной маркировки, чтобы избежать пропущенной маркировки объекта, а SATB — это аббревиатура моментального снимка в начале. Проще говоря, идея SATB состоит в том, чтобы определить, что объекты, выжившие в начале GC, живы, а все объекты во всей куче образуют снапшот; в то же время определяется, что объекты, вновь сгенерированные во время процесс GC тоже жив. , а остальные недостижимые объекты - мусор.

А то, как G1 определяет, какие объекты создаются после запуска сборщика мусора, зависит от двух указателей: prevTAMS и nextTAMS. TAMS — это аббревиатура от top at mark start Здесь мы введем несколько указателей региона:

  • Часть [нижняя, верхняя) является частью, которая была использована в регионе
  • [Верх, конец) часть области для неиспользуемой части

В начале каждой параллельной метки назначьте текущую вершину для nextTAMS, затем во время процесса параллельной маркировки вновь выделенные объекты в регионе попадают между nextTAMS и вершиной, а G1 гарантирует, что эти объекты не будут пропущены. .

Когда параллельная метка заканчивается, текущая следующая TAMS назначается предыдущей TAMS, и в соответствии с результатом метки информация о выживании объектов между [bottom, prevTAMS] сохраняется в виде растрового изображения, и затем растровое изображение может использоваться для определения является ли соответствующий объект живым или нет.

Поскольку маркировка объекта для выживания выполняется одновременно с приложением, приложение вполне может изменить ссылку на объект в процессе маркировки, поэтому, чтобы избежать пропуска маркировки, G1 использует барьер записи. Барьер записи относится к перехвату до и после действия «назначения поля ссылочного типа», а дополнительная работа может выполняться до и после присвоения. Часть барьера записи перед назначением называется барьером предварительной записи, а часть после назначения называется барьером постзаписи, и G1 использует барьер предварительной записи. Чтобы избежать пропуска меток, G1 будет рекурсивно отмечать старое значение, на которое указывает эта ссылка, перед каждым присвоением ссылки и по умолчанию будет активным, чтобы ни один объект в снимке не был пропущен. Когда старое значение больше не является живым объектом, оно фактически становится плавающим мусором и может быть оставлено только для следующего цикла сборки мусора.

Видно, что работа в упомянутом выше барьере фактически выполняется в потоке приложения. Чтобы свести к минимуму влияние барьеров записи на производительность, G1 перемещает некоторые вещи, которые должны были выполняться в барьере, в другие потоки для параллельного выполнения. Способ достижения этого разделения — через барьер записи в форме ведения журнала: приложение только записывает информацию о том, что делать в барьере, в очередь, а затем другой поток берет информацию из очереди и завершает оставшиеся действия в очереди. партии. .

Взяв в качестве примера барьер записи SATB, каждый поток Java имеет независимую SATBMarkQueue фиксированной длины, и поток приложения только помещает old_value в очередь в барьере. После заполнения очереди она будет добавлена ​​в глобальный набор очередей SATB SATBMarkQueueSet для обработки, а затем соответствующий поток Java будет заменен новой, чистой очередью для продолжения выполнения.

Очень параллельный знак периодически проверяет размер глобальной коллекции очереди WATB. Когда количество очередей в глобальном наборе превышает определенный порог, одновременный маркер обрабатывает все очереди в наборе: отметьте каждый OOP, записанный в очередь, и нажимайте его ссылочное поле на маркировочный стек и т. Д.