Тюнинг сборщика мусора G1 на задержку

В этом разделе рассматриваются советы по улучшению поведения G1 в случае общих проблем с задержкой (latency), то есть, если время паузы слишком велико.

Необычная система или использование в реальном времени

Для каждой паузы сбора мусора вывод журнала gc+cpu=info содержит строку, содержащую информацию из операционной системы с разбивкой о том, где было проведено время паузы. Примером такого вывода является User=0.19s Sys=0.00s Real=0.01s.

Пользовательское время (User) - это время, проведенное в коде виртуальной машины, системное время (Sys) - это время, проведенное в операционной системе, а реальное время (Real) - это количество абсолютного времени, прошедшего во время паузы. Если системное время относительно велико, то чаще всего причиной является среда.

Общие известные проблемы для системного времени:

  • Виртуальная машина, выделяющая или возвращающая память из памяти операционной системы, может вызвать ненужные задержки. Чтобы избежать задержек, задайте для одинакового значения минимальный и максимальный размеры кучи, используя параметры -Xms и -Xmx, и pre-touching всей памяти, используя -XX:+AlwaysPreTouch, чтобы переместить эту работу в фазу запуска виртуальной машины.
  • В частности, в Linux объединение небольших страниц в огромные страницы с помощью функции прозрачных огромных страниц (THP, Transparent Huge Pages) приводит к остановке случайных процессов, а не только во время паузы. Поскольку виртуальная машина выделяет и поддерживает много памяти, существует более высокий риск, чем обычно, что виртуальная машина будет процессом, который останавливается в течение длительного времени. Обратитесь к документации вашей операционной системы, чтобы узнать, как отключить функцию Transparent Huge Pages.
  • Запись выходных данных журнала может на некоторое время зависнуть, поскольку некоторые фоновые задачи периодически занимают всю пропускную способность ввода-вывода для жесткого диска, на который записывается журнал. Чтобы избежать этого, рассмотрите возможность использования отдельного диска для журналов или другого хранилища, например, файловой системы с резервной копией памяти.

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

Обработка ссылочного объекта занимает слишком много времени

Информация о времени, затраченном на обработку ссылочных объектов, отображается на этапе ссылочной обработки (Reference Processing). На этапе ссылочной обработки G1 обновляет ссылки на эталонные объекты в соответствии с требованиями конкретного типа эталонного объекта. По умолчанию G1 пытается распараллелить подэтапы обработки ссылок, используя следующую эвристику: для каждого -XX:ReferencesPerThread ссылочные объекты запускают один поток, ограниченный значением в -XX:ParallelGCThreads. Эту эвристику можно отключить, задав для -XX:ReferencesPerThread значение 0, чтобы использовать все доступные потоки по умолчанию, или параллелизация полностью отключена с помощью -XX:-ParallelRefProcEnabled.

Сборки только для молодых в рамках фазы "только для молодых" занимают слишком много времени

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

Другая проблема с определением размеров молодого поколения может возникнуть, если производительность приложения и, в частности, количество объектов, сохранившихся в сборке, внезапно изменится. Это может привести к резким скачкам времени сбора мусора. Может быть полезно уменьшить максимальный размер молодого поколения с помощью -XX:G1MaxNewSizePercent. Это ограничивает максимальный размер молодого поколения и, следовательно, количество объектов, которые необходимо обработать во время паузы.

Смешанные сборки занимают слишком много времени

Смешанные сборки используются, чтобы восстановить пространство в старом поколении. Набор сбора смешанных сборок содержит регионы молодого и старого поколения. Вы можете получить информацию о том, сколько времени эвакуации из регионов молодого или старого поколения влияет на время паузы, включив вывод журнала gc+ergo+cset=trace. Посмотрите на прогнозируемое время молодого региона и прогнозируемое время старого региона для регионов молодого и старого поколения соответственно.

Если прогнозируемое время для молодого региона слишком велико, тогда используйте рекомендации раздела "Сборки только для молодых в фазе только для молодых". В противном случае, чтобы уменьшить вклад областей старого поколения в время паузы, G1 предлагает три варианта:

  • Распространите восстановление региона старого поколения на большее количество сборщиков мусора, увеличив -XX:G1MixedGCCountTarget.
  • Избегайте сбора областей, которые занимают пропорционально большое количество времени, не помещая их в набор сбора кандидатов с помощью -XX:G1MixedGCLiveThresholdPercent. Во многих случаях, очень занятые регионы собирают много времени.
  • Остановите освоение пространства старым поколением раньше, чтобы G1 не собирал так много высоконаселенных регионов. В этом случае увеличьте -XX:G1HeapWastePercent.

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

Высокое обновление RS и время сканирования RS

Чтобы позволить G1 эвакуировать отдельные области старого поколения, G1 отслеживает местоположения межрегиональных ссылок, то есть ссылок, которые указывают из одного региона в другой. Набор межрегиональных ссылок, указывающих на заданную область, называется запомненным набором (remembered set, RS) этой области. Запомненные наборы должны обновляться при перемещении содержимого региона. Поддержание запомненных наборов регионов в основном происходит конкурентно. В целях повышения производительности G1 не сразу обновляет запомненный набор областей, когда приложение устанавливает новую межрегиональную ссылку между двумя объектами. Запомненные наборы запросов на обновление задерживаются и группируются для эффективности.

G1 требует полных запоминаемых наборов для сборки мусора, поэтому фаза обновления RS сборки мусора обрабатывает любые невыполненные запросы на обновление запомненного набора. Этап сканирования RS выполняет поиск ссылок на объекты в запомненных наборах, перемещает содержимое области, а затем обновляет эти ссылки на объекты в новых местоположениях. В зависимости от применения эти две фазы могут занять значительное количество времени.

Регулировка размера областей кучи с помощью опции -XX:G1HeapRegionSize влияет на количество ссылок между областями, а также на размер запомненного набора. Обработка запомненных наборов для регионов может быть значительной частью работы по сбору мусора, так что это напрямую влияет на достижимое максимальное время паузы. Более крупные регионы, как правило, имеют меньшее количество межрегиональных ссылок, поэтому относительный объем работы, потраченной на их обработку, уменьшается, хотя в то же время более крупные регионы могут означать большее количество живых объектов для эвакуации в каждом регионе, что увеличивает время для других фаз.

G1 пытается запланировать конкурентную обработку обновлений запомненного набора так, чтобы этап RS обновления занимал приблизительно -XX:G1RSetUpdatingPauseTimePercent процент от разрешенного максимального времени паузы. Уменьшая это значение, G1 обычно одновременно выполняет больше операций по запоминанию заданного набора.

Ложное высокое время обновления RS в сочетании с тем, что приложение выделяет большие объекты, может быть вызвано оптимизацией, которая пытается уменьшить количество конкурентных обновлений запомненного набора путем его пакетирования. Если приложение, которое создало такой пакет, происходит непосредственно перед сборкой мусора, то сборка мусора должна обрабатывать всю эту работу в части времени обновления RS в паузе. Используйте -XX:-ReduceInitialCardMarks, чтобы отключить это поведение и потенциально избежать этих ситуаций.

Время сканирования RS также определяется степенью сжатия, которую G1 выполняет, чтобы сохранить запомненный установленный размер хранилища низким. Чем компактнее запомненный набор хранится в памяти, тем больше времени требуется для извлечения сохраненных значений во время сбора мусора. G1 автоматически выполняет это сжатие, называемое укрупнением запомненных наборов, одновременно обновляя запомненные наборы в зависимости от текущего размера запомненного набора этого региона. В частности, при самом высоком уровне сжатия получение фактических данных может быть очень медленным. Опция -XX:G1SummarizeRSetStatsPeriod в сочетании с gc+remset=trace журналирование уровня трассировки показывает, происходит ли это укрупнение. Если это так, то X в строке "Did <X> coarsenings" в "Before GC Summary" разделе показывает высокое значение. Параметр -XX:G1RSetRegionEntries может быть значительно увеличен, чтобы уменьшить количество этих укрупнений. Избегайте использования этой подробной записи запомненных наборов в производственных средах, поскольку сбор этих данных может занять значительное время.


Читайте также:


Комментарии

Популярные сообщения из этого блога

Методы класса Object в Java

Как получить текущий timestamp в Java

Основные опции JVM для повышения производительности и отладки