openjdk.ruOpenJDK на русском

JEP 345: NUMA-Aware Memory Allocation for G1

Выделение памяти с учётом NUMA для G1

ОтветственныйSangheon Kim
ТипFeature
ОбластьJDK
СтатусClosed / Delivered
Выпуск14
Компонентhotspot / gc
Обсуждениеhotspot dash gc dash dev at openjdk dot java dot net
ТрудоёмкостьM
ДлительностьM
DuplicatesJEP 157: G1 GC: NUMA-Aware Allocation
РецензентыMikael Vidstedt, Stefan Johansson, Thomas Schatzl
ОдобренMikael Vidstedt
Создан2018/09/06 22:46
Обновлён2020/02/27 21:46
Задача8210473

Аннотация

Повысить производительность G1 на больших машинах за счёт выделения памяти с учётом NUMA.

Что не является целью

  • Реализация поддержки NUMA в сборщиках мусора, отличных от G1, не является целью.
  • Поддержка операционных систем, отличных от Linux, не является целью.
  • Не является целью добавлять учёт NUMA в другие части G1, такие как перехват задач из очередей (task queue stealing), remembered sets или refinement.

Мотивация

В современных многопроцессорных машинах всё чаще используется неоднородный доступ к памяти (non-uniform memory access, NUMA): память находится на разном расстоянии от разных сокетов или ядер. Обращения к памяти между сокетами различаются по производительности: доступ к более удалённым сокетам, как правило, имеет бо́льшую задержку.

Параллельный сборщик мусора, который включается флагом -XX:+UseParallelGC, учитывает NUMA уже много лет. Это помогло повысить производительность конфигураций, в которых одна JVM работает на нескольких сокетах. Другие сборщики мусора HotSpot этой возможности не имели, поэтому не могли использовать такое вертикальное масштабирование на несколько сокетов с NUMA. В частности, крупные корпоративные приложения обычно работают с большой кучей на нескольких сокетах, но при этом хотят сохранить преимущество в управляемости, которое даёт работа в одной JVM. Пользователи сборщика мусора G1 всё чаще упираются в это ограничение масштабирования.

Описание

Куча G1 организована как набор регионов фиксированного размера. Обычно регион — это набор физических страниц, хотя при использовании больших страниц (через -XX:+UseLargePages) одну физическую страницу могут составлять несколько регионов.

Если указан параметр +XX:+UseNUMA, то при инициализации JVM регионы будут равномерно распределены по всем доступным узлам NUMA.

Закрепление узла NUMA за каждым регионом в самом начале несколько негибко, но это можно смягчить следующими улучшениями. Чтобы выделить новый объект для потока-мутатора, G1 может потребоваться выделить новый регион. При этом G1 будет в первую очередь выбирать свободный регион на том узле NUMA, к которому привязан текущий поток, чтобы объект оставался на том же узле NUMA в молодом поколении. Если при выделении региона для мутатора на том же узле NUMA нет свободного региона, G1 запустит сборку мусора. Альтернативная идея, которую предстоит оценить, — искать свободные регионы на других узлах NUMA в порядке удалённости, начиная с ближайшего узла NUMA.

Мы не будем пытаться сохранять объекты на том же узле NUMA в старом поколении.

Humongous-регионы (регионы для очень больших объектов) исключены из этой политики выделения. Для этих регионов мы не будем делать ничего особенного.

Тестирование

Существующие тесты с параметром -XX:+UseNUMA должны выявить любые проблемы с корректностью. Мы предполагаем, что для тестирования используется оборудование с NUMA.

Когда выделение памяти с учётом NUMA выключено, производительность не должна отличаться от исходного кода.

Риски и допущения

Мы предполагаем, что к большинству короткоживущих объектов часто обращается поток, который их выделил. Это безусловно верно для большинства короткоживущих объектов в большинстве объектно-ориентированных программ. Однако есть программы, для которых это допущение не вполне выполняется, поэтому в некоторых случаях возможно снижение производительности. Кроме того, выигрыш зависит ещё и от сочетания двух факторов: насколько выражена NUMA-архитектура нижележащей системы и как часто потоки на таких системах переносятся между узлами NUMA, особенно при высокой нагрузке.