Слава Java-программистов, послушайте R на ZGC JDK11

Java

предисловие

А вот и ZGC!!!Программисты Java могут с честью уйти от надоедливых пауз и настройки GC. Результатом ZGC является то, что независимо от того, сколько памяти кучи вы открываете (1288G? 2T?), он может гарантировать паузу JVM менее 10 миллисекунд.

В бенчмарке SPECjbb 2015 под кучей 128G максимальное время паузы составляет всего 1,68 мс (не среднее, не 90%, 99%, это Макс!), намного ниже исходной цели - консервативные 10 мс тоже далеко лучше, чем до поколения G1.

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

Если статья слишком длинная и вы не хотите ее читать, вам просто нужно запомнить следующее предложение из R:

По сравнению с традиционным алгоритмом маркировки объектов, ZGC маркирует указатель и добавляет Load Barrier (барьер чтения) при доступе к указателю.Например, когда объект перемещается GC, цвет указателя будет неправильным, и этот барьер сначала обновит указатель до эффективного адреса, а затем вернет, то есть всегда есть вероятность, что только один объект будет тормозить при чтении, и нет Stop The World, чтобы сохранить согласованность приложения с ГК.

На самом деле, сборщик мусора Azul JDK ace C4 уже давно стал легендой с паузой до десяти миллисекунд. Раньше я был мажором R в Azul, и я был хорошо знаком с алгоритмом и результатами JDK11 ZGC.Поговорив с Пером Лиденом, лидером ZGC, я подтвердил, что ZGC и Azul Pauseless GC — да, подождите, цена , да. (На момент написания этой статьи остальные студенты - превью, а R - имперский опрос. Долго подумав, я выбрал слово "эквивалент")

(большой выстрел Пера в значительной степени в JVMLS)

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

1. Почти все этапы выполняются одновременно

    Параллельность здесь означает, что потоки приложения и потоки GC идут рука об руку, не блокируя друг друга.

    Почти, есть еще три очень коротких этапа STW, так что ZGC — это не Zero Pause GC.

    Р: «Например, на начальном этапе Pause Mark Start требуется сканирование корневого набора, включая глобальные переменные, указатели объектов в стеках потоков и т. д., но не указатели объектов в куче GC, поэтому эта пауза не изменит с размером кучи GC (но он будет меняться в зависимости от количества потоков, размера стека потоков и т. д.)" -- так что ZGC может побить сундук, независимо от того, насколько велика куча, пауза менее 10 мс.

    2. Гарантийный механизм параллельного выполнения — Colored Pointer и Load Barrier.

    Большое предложение R перед принципом закончено. Colored Pointer заимствует несколько битов у 64-битного указателя для представления Finalizable, Remapped, Marked1 и Marked0. Таким образом, он не поддерживает ни 32-битные указатели, ни сжатые указатели, а верхний предел кучи составляет 4 ТБ.

    Если есть Загрузочный барьер, на разных этапах вы увидите, нужно ли вам сделать что-то особенное (Медленный путь) в соответствии с цветом указателя. Обратите внимание, что на рисунке ниже барьер чтения требуется только для первого оператора, а не для последних трех, например, когда значение является примитивным типом.

    R также упомянул барьер ZGC Load Value Barrier, который отличается от коллектора Shenandoah от Red Hat.Последний выбрал относительно простой Brooks Pointer в 1970-х, в то время как первый добавил функцию самовосстановления к очень старому барьеру Бейкера. код:

    Object a = obj.x; 

    Object b = obj.x;

    Обе строки кода вставили барьер чтения, но после первого барьера чтения ZGC не только имеет новое значение a, но и значение самого obj.x при самовосстановлении и напрямую входит в FastPath на втором барьере чтения. , потребления нет, и Shenandoah не будет исправлять значение obj.x, а второй барьер чтения снова требует SlowPath.

    3. Разделите регион, как G1, но более гибко.

    ZGC делит кучу на регионы как единицы для очистки, перемещения и параллельного распределения работы потоков GC.

    Однако G1 с самого начала делит кучу на регионы фиксированного размера, в то время как ZGC может иметь три группы размеров: 2 МБ, 32 МБ и N × 2 МБ, динамически создавать и уничтожать регионы и динамически определять размер регионов.

    Объекты размером менее 256 КБ размещаются на маленькой странице, объекты размером менее 4 М — на средней странице, а объекты размером более 4 М — на большой странице.

    Таким образом, ZGC может лучше справляться с выделением больших объектов.

     

    4. Как и G1, он будет выполнять компактирование-сжатие

    CMS это Mark-Swap.После маркировки просроченных объектов они будут утилизированы на месте, что вызовет фрагментацию памяти, и будет все труднее найти непрерывное место.Он не будет сжат до тех пор, пока не произойдет Full GC.

    ZGC — это Mark-Compact, который перемещает все живые объекты в другой регион и перерабатывает исходный регион.

    А G1 — сборщик инкрементного копирования, который тоже будет делать сжатие.

    Ниже приводится грубая волна процесса переработки десятки раз, а мелкие этапы пропущены:

     

    1. Pause Mark Start - начальная отметка паузы

      Приостановите JVM, чтобы отметить корневой объект, 1, 2 и 4 отмечены как активные.

      2. Параллельная метка - Параллельная метка

      Рекурсивно помечая другие объекты одновременно, 5 и 8 также помечаются как живые.

      3. Relocate - переместить объект

      Сравнение показало, что объекты 3, 6 и 7 являются объектами с истекшим сроком действия, то есть две серые области в середине необходимо сжать и очистить, поэтому объекты 4, 5 и 8 последовательно перемещаются в новую область на дальнем конце. правильно. Во время хода есть форвардная таблица для записи этого хода.

      R здесь, чтобы похвалить функцию быстрого выпуска C4/ZGC: после того, как все живые объекты будут удалены, область может быть немедленно освобождена и использована в качестве области для следующей области для сканирования. Так что теоретически для сбора всей кучи нужен только один пустой регион.

      А Shenandoah от RedHat нуждается в 1/2 Heap, чтобы быть пустым, из-за дизайна прямого указателя.

      4. Remap - правильный указатель

      Наконец, указатели должным образом обновляются, чтобы указывать на новый адрес. Здесь R также упомянул одну изюминку: «Remap на предыдущем этапе и Mark на следующем этапе смешиваются вместе, что очень эффективно и экономит накладные расходы, связанные с повторным обходом графа объектов».

      5. Нет набора запоминания, который G1 занимает память, и нет накладных расходов на барьер записи.

      То, как G1 гарантирует, что «каждая пауза GC не будет слишком длинной», представляет собой пошаговую очистку, которая «очищает только часть региона, а не весь регион за раз».

      При независимой очистке региона требуется набор RememberSet для записи отношения ссылки на объект между регионами, чтобы на него можно было положиться при расчете живучести объектов без сканирования всей кучи.RS обычно составляет 20% всей кучи. или выше.

      Также необходимо использовать технологию Write Barrier.Когда G1 обычно пишет ссылки, а GC перемещает объекты, он должен синхронно обновлять RememberSe для отслеживания ссылок между поколениями и регионами, что особенно важно. В CMS между новым и старым поколениями есть только CardTable, который намного легче.

      У ZGC почти нет паузы, так что деление Регионов не для инкрементной утилизации.Все Регионы будут перерабатываться каждый раз, поэтому нет необходимости в этом MemorySet, который занимает память, и потому, что он пока даже не реализован , так что полностью нет барьера записи.

      6. Поддержка архитектуры Numa

      Теперь серверы с несколькими сокетами ЦП — это все архитектуры Numa.Например, сервер с двумя сокетами ЦП (24 ядра) и памятью 64G, 12 ядер на одном из ЦП могут получить доступ к принадлежащей ему локальной памяти 32G.Гораздо быстрее, чем доступ еще 32G удаленной памяти.

      Алгоритм Parallel Scavenger JDK поддерживает архитектуру Numa и показал улучшение на 40% по сравнению с эталонным тестом SPEC JBB 2005.

      Принцип заключается в том, что при подаче заявки на память в куче, подайте заявку на некоторую память каждого Numa Node.Когда поток выделяет объекты, в соответствии с которыми в данный момент работает ЦП, он размещается в памяти, близкой к этому ЦП, и поток продолжается. вниз, этот объект обычно пересматривается, и если поток не был переключен, то товарищ ЦП все еще обращается, поэтому это быстро.

      Но, к сожалению, CMS, G1 не поддерживает Numa, а теперь ZGC снова сделал простую поддержку, хахаха.

      Большое дополнение, G1 также планирует поддерживать Numa: http://openjdk.java.net/jeps/157.

      7. Параллельно

      Он представлен на официальном сайте ZGC, В сценарии с 32-ядерным сервером и 128-гигабайтной кучей в предыдущем тесте производительности его конфигурация следующая:

      20 параллельных GCThreads,Работайте параллельно на этих трех очень коротких этапах STW - пометьте корни, обработайте слабые корни (StringTable, слабые дескрипторы JNI и т. д.) и переместите корни;

      4 ConcGCThreads, работайте параллельно с приложением на других этапах - Пометить, Обработать ссылку, Переместить. Их всего четыре, и Гао Фэнлю изо всех сил старается не конкурировать с приложением за процессор.

      В начале ConcCGCThreads заняты своими равномерно распределенными регионами.Если поток занят первым, он попытается «украсть» регионы, которые другие потоки не сделали для работы, что очень усердно.

      Восемь, одно поколение

      Нет генерации, это должно быть единственной слабостью ZGC. Итак, R сказал, что уровень ZGC находится между ранним PauselessGC AZul и алгоритмом поколения C4 — C4 в коде называется GPGC, Generational Pauseless GC.

      Поколенческое поколение изначально было основано на предположении, что большинство объектов умирают молодыми, поэтому новое поколение и старое поколение используют разные алгоритмы GC. Но C4 — это уже полнопроцессный параллельный алгоритм, зачем ему генерация? 

      Р сказал:

      «Потому что скорость выделения объектов (скорость выделения), которую может выдержать C4 поколения, примерно в 10 раз выше, чем у оригинального PGC.

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

      И Per очень сложно реализовать по поколениям, поэтому сначала реализуется относительно простая и удобная версия для одного поколения. Таким образом, если ZGC сталкивается с очень высокой скоростью выделения объектов, единственным эффективным методом «настройки» в настоящее время является увеличение размера всей кучи GC, чтобы дать ZGC больше передышки. "

      резюме

      ZGC заставляет Java иметь лицо и с нетерпением ждет подобных вещей, но я не специалист по Java! ! !

      Все виды записей чата R big на протяжении всего процесса, если вы не включите его, вы не большой поклонник R! ! ! !

      Резюме 2

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

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

      использованная литература

      1. Вики ZGC:

      https://wiki.openjdk.java.net/display/zgc/Main

      2. Чжиху из Big R ответил:

      https://www.zhihu.com/question/287945354/answer/458761494

      3. Насколько ненормальным является коллектор ZGC? Хэ Чжуофань ImportSource

      Многие изображения в этой статье заимствованы, спасибо. Ссылка слишком длинная для размещения, все ищут по названию.

      4. ПЕРВЫЙ ВЗГЛЯД НА ZGC:

      http://dinfuehr.github.io/blog/a-first-look-into-zgc/

      5. Статья AZul "Алгоритм сборки мусора без пауз":

      https://www.usenix.org/legacy/events/vee05/full_papers/p46-click.pdf

      6. Эталонная реализация C4 с открытым исходным кодом AZul, реализация оригинальной бумаги

      https://github.com/GregBowyer/ManagedRuntimeInitiative/tree/master/MRI-J/hotspot/src/azshare/vm/