Самое классное место в Java-программе — это ее механизм GC, и разработчикам не нужно обращать внимание на использование памяти и переработку. В то же время самой головной болью Java-программы является также ее механизм GC, потому что овладение JVM и настройкой GC — очень сложная вещь. После ParalleLoldGC, CMS, G1 новый "JDK11 приносит"ZGC«Какую проблему это решило для нас? Oracle официально представила масштабируемый сборщик мусора с низкой задержкой. Итак, его цель "Сокращение времени простояд.», что приведет к снижению пропускной способности. Снижение пропускной способности не является большой проблемой, и масштабирование нескольких серверов по горизонтали может решить эту проблему.
ZGC цель
Как показано на рисунке ниже, ZGC преследует четыре основные цели:
- Поддерживает терабайтные кучи. Вы можете вынести это? Жесткий диск в нашей производственной среде еще не достиг ТБ, что должно удовлетворить потребности всех приложений JAVA в ближайшие десять лет.
- 最大GC停顿时间不超10ms。 Вы можете вынести это?目前一般线上环境运行良好的JAVA应用Minor GC停顿时间在10ms左右,Major GC一般都需要100ms以上(G1可以调节停顿时间,但是如果调的过低的话,反而会适得其反),之所以能做到这一点是因为它的停顿时间主要跟Root扫描有关,而Root数量和堆大小是没有任何关系的。
- Заложите основу для будущих функций GC. Круто круто!
- В худшем случае пропускная способность снижается на 15%. Все в порядке, время паузы достаточно хорошее. Что касается пропускной способности, то ее можно решить за считанные минуты путем расширения мощностей.
Кроме того, Oracle официально упомянул, что его самым большим преимуществом является то, что время паузы не будет увеличиваться с увеличением кучи! Другими словами, время паузы десятков куч G меньше 10 мс, а время паузы сотен куч G или даже куч T меньше 10 мс.
Обзор ZGC
Далее мы дадим обзор ZGC с нескольких сторон.
- New GC
- Single Generation
- Region Based
- Partial Compaction
- NUMA-aware
- Colored Pointers
- Load Barriers
- ZGC tuning
- Change Log
New GC
ZGC — совершенно новый сборщик мусора, который полностью отличается от любых предыдущих сборщиков мусора HotSpot, таких как: PS, CMS, G1 и т. д. Если и есть что-то, на что он больше всего похож, так это коммерческий сборщик мусора Azul: "C4», алгоритм, используемый ZGC, представляет собой Pauseless GC, предложенный Azul Systems много лет назад, и его реализация находится между Pauseless GC ранней виртуальной машины Azul и C4 более поздней виртуальной машины Zing. Однако следует отметить, что ZGC в JDK11 может работать только в операционной системе Linux64. В JDK14 добавлена поддержка платформ MacOS и Window:
Как показано на рисунке ниже, это результат сравнения испытаний под давлением ZGC, Parallel и G1 (CMS помечен как устаревший в JDK9 и полностью удален в более поздних версиях, поэтому он не входит в объем сравнения). Мы можем ясно видеть, что с точки зрения времени паузы ZGC на 100% меньше 10 мс и существует в секундах:
Далее взгляните на процесс сборки мусора ZGC, как показано на следующем рисунке. Как видно из рисунка, ZGC еще не добился полного одновременного выполнения всего процесса GC, осталось три этапа STW, а остальные три этапа являются этапами параллельного выполнения:
- Pause Mark Start
Этот шаг предназначен для инициализации метки. Как и CMS и G1, он в основном сканирует коллекцию Root. «GC Root — это набор ссылок, которые должны быть активны, а не объекты». Например: ссылки на объекты в активном фрейме стека, указывающие на кучу GC, классы, загруженные загрузчиком классов Bootstrap/System, дескрипторы JNI, статические переменные ссылочного типа, ссылки в пуле констант String, указатели на стек потоков/родные объекты стека и т. д. , но не указатели объектов в куче сборщика мусора. Таким образом, время STW этого шага очень короткое и не имеет ничего общего с размером кучи. Однако он будет варьироваться в зависимости от количества потоков, размера стека потоков и т.п.
- Concurrent Mark/Remap
Второй шаг — это параллельная фаза маркировки, которая продолжает маркировать уцелевшие объекты на основе первого шага. После одновременной маркировки также следует короткая пауза (Pause Mark End), чтобы убедиться, что все объекты отмечены.
- Concurrent Prepare for Relocate
То есть, чтобы подготовиться к этапу «Перемещение», выберите набор регионов, который нужно пометить и отсортировать следующим, этот этап также выполняется параллельно. Далее будет шаг Pause Relocate Start, его роль заключается в перемещении только ссылки на объект корневой коллекции, поэтому этот этап STW не будет приостанавливаться слишком долго.
- Concurrent Relocate
Наконец, существует фаза параллельной переработки, которая перемещает уцелевшие объекты в коллекции регионов, которые необходимо отсортировать, выбранные на предыдущем этапе, в новый регион (такое поведение называется ""Relocate, то есть переместить объект), как показано на изображении выше. После того, как действие «Переместить» завершено, первоначально занятый регион может быть немедленно возвращен и использован для размещения следующего объекта. У внимательных учеников могут возникнуть вопросы, неужели это конец? После Relocate изменились адреса объектов, как программа может нормально работать с этими объектами? Это зависит от барьера нагрузки, который будет подробно объяснен далее.
Single Generation
Единое поколение, а именно ZGC»нет поколения". Мы знаем, что предыдущий сборщик мусора был генерационным, потому что он произошел от ""Большинство субъектов умирают в мгновение ока"" предположение, и на самом деле поведение распределения объектов в большинстве систем действительно соответствует этому предположению.
Так почему же ZGC не является поколением? Поскольку реализация на основе поколений проблематична, автор сначала реализует относительно простую и удобную версию на одном поколении. Объясняя это с точки зрения наших национальных условий, наверное, так: нагрузки слишком много, а рабочей силы не хватает Босс, давайте сначала на версию 1.0! ! !
Region Based
Это то же самое, что и G1, который представляет собой сборщик мусора, разработанный на основе региона. Регион в ZGC также называется "ZPages", ZPages динамически создаются и динамически уничтожаются. Однако, немного отличаясь от G1, размер каждой области G1 точно такой же, в то время как размер области ZGC разделен на 3 категории: 2 МБ, 32 МБ, N×2 МБ, так что гибкость лучше:
Partial Compaction
Частичное сжатие, очень похожее на G1. Когда предыдущие ParallelOldGC и CMS GC сжимают старую область, независимо от того, насколько велика старая область, она должна быть сжата целиком (сжатие), поэтому чем больше старая область, тем больше времени определенно займет сжатие, что приведет к более длительному сжатию. паузы.
G1 и ZGC основаны на дизайне региона, во время восстановления они будут выбирать только часть региона для переработки, в процессе переработки используется алгоритм Mark-Compact, регион скоро будет восстановлен в живых объектах. скопированный в новый регион, это новое размещение объекта региона будет очень компактным, почти без мусора. Алгоритм сборки мусора у этой точки и у G1 одинаков.
NUMA-aware
Numa соответствует UMA, uma — унифицированной архитектуре доступа к памяти, NUMA — неунифицированной архитектуре доступа к памяти. Uma представляет только одну память, все ЦП имеют доступ к этой памяти, тогда возникают проблемы с конкуренцией (конкуренция за доступ к шине памяти), конкуренция будет заблокирована, эффективность блокировки будет затронута, а количество ядер ЦП больше интенсивная конкуренция. Слова Numa соответствуют памяти, и этот ЦП находится ближе всего к этому ЦП в этом блоке, каждый ЦП имеет приоритет, и эта эффективность естественным образом улучшится:
Архитектура сервера NUMA всегда была очень популярна в средних и больших системах, а также является высокопроизводительным решением, особенно с точки зрения задержки системы. ZGC может автоматически воспринимать архитектуру NUMA и в полной мере использовать функции архитектуры NUMA.
Colored Pointers
Цветные указатели, что такое цветные указатели? Как показано на рисунке ниже, одна из основных конструкций ZGC. Информация GC предыдущего сборщика мусора хранится в заголовке объекта, а информация GC ZGC хранится в указателе. Каждый объект имеет 64-битный указатель, и эти 64 бита делятся на:
- 18 бит: зарезервировано для использования в будущем;
- 1-й бит: флаг Finalizable, второй бит связан с параллельной обработкой ссылок, это означает, что доступ к этому объекту возможен только через финализатор;
- 1 бит: флаг переназначения, после установки значения этого бита объект не указывает на набор перемещений (набор перемещений представляет собой набор регионов, для которого требуется GC);
- 1 бит: логотип Marked1;
- 1 бит: идентификатор Marked0, а Marked1 выше — отмеченные объекты для помощи GC;
- 42 бита: адрес объекта (чтобы он мог поддерживать 2^42=4T памяти):
Анализируя указатель объекта после настройки ZGC, мы знаем, что указатель объекта должен быть 64-битным, тогда ZGC не может поддерживать 32-битную операционную систему, а также не может поддерживать сжатый указатель (CompressedOops, сжатый указатель тоже 32-битный).
Load Barriers
Это должно быть переведено в барьер чтения (соответствующий барьер записи — Write Barrier, предыдущий GC использовал Write Barrier, на этот раз ZGC использует совершенно другую схему), это очень важная особенность ZGC. На этапе маркировки и перемещения объектов каждый "Считать указатель из ссылочного типа объекта в кучеВремя», нам нужно добавить барьеры нагрузки. Итак, как мы это понимаем? (Только чтение плюс барьер, когда fieldA является целью) посмотрите на следующий код, первая строка кода, в которой мы пытаемся прочитать кучи ссылок на объекты obj.fieldA и присвоить ссылку o. Если в этот раз объект двигался в GC, то JVM добавит барьер чтения, этот барьер будет считывать адрес, указатель обновляется до нового объекта, а указатель кучи «вносит поправки» в исходное поле. Таким образом, даже если объект перемещается с помощью GC, барьер чтения найдет и зафиксирует указатель, поэтому эффективный код приложения всегда будет удерживать указатель после обновлений и не требует STW. Итак, JVM — это как определить, что объект перемещается по ней? Является ли использование цветовых указателей упомянутым выше, если указатель плохого цвета, то программа не может выполняться вниз, нужно "slow path», исправьте указатель, если указатель Good Color, то выполните его нормально:
Это действие очень похоже на вращение CAS, используемое в параллелизме JDK? Считанное значение оказывается недопустимым и требует повторного чтения. В ZGC указатель, удерживаемый ранее, недействителен после GC, и указатель необходимо исправить через барьер чтения.
Следующие три строки кода не требуют добавления барьеров чтения: Object p = o не читает данные из кучи, o.doSomething() не читает данные из кучи, obj.fieldB не является ссылкой на объект, а является атомарным. тип.
Именно из-за наличия барьеров нагрузки пропускная способность приложений, сконфигурированных ZGC, будет ниже. Официальные тестовые данные — это дополнительные 4% накладных расходов:
Итак, что является основанием для суждения о том, является ли объект плохим цветом или хорошим цветом? Он основан на 4 битах цветных указателей, упомянутых в предыдущем абзаце. Когда добавляется барьер чтения, в соответствии с 4-битной информацией в указателе объекта можно узнать, что текущий объект имеет плохой/хороший цвет.
«Расширенное чтение»: поскольку младший 42-битный указатель может поддерживать память 4T, можем ли мы достичь цели поддержки большей памяти, зарезервировав больше битов для адреса объекта? Ответ определенно нет. Поскольку текущая адресная шина материнской платы имеет ширину всего 48 бит, а 4 бита являются битами цвета, осталось только 44 бита, что ограничено текущим оборудованием, ZGC может поддерживать только максимальную память 16T, а JDK13 расширяет максимально поддерживаемую кучу. память от 4T до 16T.
ZGC tuning
Включить ZGC относительно просто, установите параметр JVM: -xx:+lockexperimentAlVMOPTIONS "-xx:+usezgc". Настройка не сложная, т.к. параметры настройки ZGC не так много, не так сложны, как CMS. Это то же самое, что и G1, который можно настроить, и большую часть работы JVM можно сделать хорошо. На следующем рисунке показаны параметры, которые может настраивать ZGC:
Некоторые параметры более подробно описаны ниже.
UseNUMA
ZGC поддерживает NUMA по умолчанию, однако, если JVM обнаружит, что система привязана к подмножеству процессоров, она автоматически отключит NUMA. Мы можем отображать включенным параметром -XX:+UseNUMA или отключенным параметром -XX:-UseNUMA. При работе на сервере NUMA с установленным параметром -XX:+UseNUMA улучшение производительности заметно.
UseLargePages
Настройка ZGC для использования больших страниц обычно приводит к повышению производительности с точки зрения пропускной способности, задержки, времени запуска и т. д. И явных минусов нет, разве что процесс настройки немного сложнее. Потому что для этого требуются привилегии root, поэтому использование больших страниц не включено по умолчанию.
ConcGCThreads
ZGC — это параллельный сборщик мусора, поэтому количество параллельных потоков GC очень важно. Если вы установите количество параллельных потоков GC больше, это означает, что количество потоков приложения будет меньше, что определенно не способствует стабильной работе системы приложений. Этот параметр ZGC может установить автоматически, если не полностью уверен. Этот параметр лучше не устанавливать.
ParallelGCThreads
Это количество параллельных потоков, которое отличается от предыдущего параметра ConcGCThreads.ConcGCThreads указывает количество потоков GC, когда потоки GC и потоки приложений выполняются «одновременно». ParallelGCThreads представляет количество «параллельных» потоков GC на этапе STW во время GC (например, корневое сканирование на первом этапе).В настоящее время есть только потоки GC и нет потоков приложений. Здесь автор объясняет «разницу между параллелизмом и параллелизмом» в JVM, что также облегчает понимание ошибок в JVM.
ZUncommit
Прежде чем разобраться с этим аргументом, давайте поговорим о JVM и о том, как поведение приложения освобождает память. Бывшие сборщики мусора, такие как ParallelOldGC и CMS, до тех пор, пока запрошена память JVM, даже несмотря на то, что GC восстанавливает много места в памяти, память JVM и не будет возвращена в операционную систему. Эта команда заставит топ видеть, что RSS становится только выше и обычно превышает значение Xmx (см. статью :).
Однако по умолчанию ZGC возвращает операционной системе память, которая больше не используется. Это полезно для приложений и серверов, которые обращают внимание на использование памяти. Это поведение можно отключить с помощью параметра JVM **-XX:-ZUncommit**. Однако независимо от того, как он будет возвращен, JVM по крайней мере сохранит объем памяти, указанный параметром Xms, а это означает, что когда Xmx совпадает с Xms, этот параметр не действует.
Есть еще один параметр, который работает с этим параметром: - "XX:ZUncommitDelay=sec", по умолчанию 300 секунд. Этот параметр указывает максимальную задержку для памяти, которая больше не используется, перед возвратом в операционную систему. Поскольку память, которая больше не используется, не должна быть немедленно возвращена в операционную систему, что приведет к частому возврату и поведению приложения, поэтому этот параметр используется для управления временем, которое требуется для возврата памяти, которая больше не используется. операционная система.
Change Log
Далее давайте посмотрим, какие функции ZGC перенесла с JDK11 на JDK15:
JDK 15 (under development)
- Improved NUMA awareness
- Support for Class Data Sharing (CDS)
- Support for placing the heap on NVRAM
JDK 14
- macOS support (JEP 364)
- Windows support (JEP 365)
- Support for tiny/small heaps (down to 8M)
- Support for JFR leak profiler
- Support for limited and discontiguous address space
- Parallel pre-touch (when using -XX:+AlwaysPreTouch)
- Performance improvements (clone intrinsic, etc)
- Stability improvements
JDK 13
- Increased max heap size from 4TB to 16TB
- Support for uncommitting unused memory (JEP 351)
- Support for -XX:SoftMaxHeapSIze
- Support for the Linux/AArch64 platform
- Reduced Time-To-Safepoint
JDK 12
- Support for concurrent class unloading
- Further pause time reductions
JDK 11
- Initial version of ZGC
- Does not support class unloading (using -XX:+ClassUnloading has no effect)
Прочитав три вещи ❤️
Если вы считаете, что этот контент очень полезен для вас, я хотел бы пригласить вас сделать мне три небольших одолжения:
-
Лайки, репосты и ваши "лайки и комментарии" - движущая сила моего творчества.
-
Обратите внимание на паблик «java rotten pigskin» и время от времени делитесь оригинальными знаниями.
-
В то же время вы можете рассчитывать на последующие статьи🚀
Автор: А Фэй Джавер
Первоисточник:club.perf.com/article/679…