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

JEP 308: Improve Dynamic Number of Thread Sizing for G1

Улучшение динамического определения числа потоков в G1

ОтветственныйThomas Schatzl
ТипFeature
ОбластьImplementation
СтатусClosed / Withdrawn
Компонентhotspot / gc
Обсуждениеhotspot dash gc dash dev at openjdk dot java dot net
ТрудоёмкостьL
ДлительностьM
РецензентыMikael Vidstedt
ОдобренMikael Vidstedt
Создан2017/01/13 14:37
Обновлён2022/03/04 13:53
Задача8172792

Аннотация

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

Цели

Улучшить политики G1 по умолчанию для определения числа потоков в следующих областях:

  • определение числа потоков, используемых во время пауз сборки мусора, при refinement и при маркировке,

  • в частности, для обработки ссылок автоматически определять, следует ли включать параллельную обработку, и определять оптимальное число потоков,

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

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

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

Изменения ограничиваются тем, как используются ресурсы в существующих алгоритмах; сами алгоритмы сборки мусора не меняются.

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

Критерии успеха

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

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

Мотивация

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

  • рабочие потоки для операций GC всегда выделяются заранее, из-за чего замедляется запуск и растёт расход памяти, особенно для небольших и недолго работающих пакетных задач.

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

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

Описание

Главное изменение в управлении потоками: семантика текущих параметров числа потоков (-XX:ParallelGCThreads, -XX:ConcGCThreads) немного изменится. Вместо точного числа потоков, используемых при GC, маркировке и refinement, они всегда будут означать (если ещё не означают) максимальное число потоков, которое G1 разрешено использовать. Кроме того, по умолчанию потоки не будут создаваться заранее в полном объёме при запуске, а будут создаваться лениво, по мере необходимости.

Число потоков будет определяться числом рабочих элементов для конкретной фазы работы. Точное определение рабочего элемента будет зависеть от фазы, а итоговое число потоков будут определять эвристики (например, для фазы эвакуации при GC число потоков для этой фазы будет определяться ожидаемым объёмом живых данных, которые предстоит эвакуировать в этой фазе). О принятых решениях нужно сообщать по подходящим каналам (например, в сообщениях журнала).

Для таких фаз, как обработка ссылок, где сейчас пользователю нужно вручную включать параллельную обработку (через -XX:+ParallelRefProcEnabled), G1 будет сам решать, включать ли её, и если да, то определять число потоков для каждой фазы исходя из числа рабочих элементов, которые нужно обработать.

Решение о том, освобождать ли ресурсы потоков после длительного простоя, пока не принято.

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

Альтернативы

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

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

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

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

Эвристики, которые мы намерены реализовать, появились в результате обсуждений со многими пользователями и работы по настройке. Эти сведения могли поступить лишь от нерепрезентативной части сценариев использования или от сценариев, которые уже перестали быть репрезентативными. В итоге это может сделать данную работу ненужной. Некоторые изменения из-за изменённых эвристик могут вызвать непреднамеренное снижение производительности. Часть этой работы требует экспериментов с эвристиками, которые в итоге могут оказаться неудачными. У нас есть на этот счёт идеи, которые выглядят правдоподобными, но непредвиденные взаимодействия внутри сборщика мусора, а также между сборщиком мусора и приложениями могут привести к тому, что эти эвристики будут работать очень плохо. В таких случаях мы намерены упрощать эвристики, пока в конце концов пользователю не придётся задавать больше подробностей.