«CMS» (Concurrent Mark-Sweep) — это алгоритм gc, который широко используется в приложениях, «критичных ко времени отклика».

Для молодого поколения, минорный gc, CMS также остановит все потоки приложений, но «ParNew» выполняет сканирование в многопоточном режиме, а сканирование молодого поколения происходит быстро, потому что оно маленькое.

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

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

CMS включается с помощью -XX:+UseConcMarkSweepGC -XX:+UseParNewGC.

Общее внимание

1. Никогда не указывайте кучу больше, чем физическая память

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

2. Установите для начального и максимального размера кучи одинаковое значение.

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

3. Сделайте нужный размер Generations

Как мы знаем, куча разделена на множество регионов. Чем больше используется молодое поколение, тем меньше шансов, что молодые gc появятся (хотя и медленнее). Меньшее старое поколение использовало более полные gcs.

4. Сделать Пермскую генерацию неполной

Изменение размера perm-gen потребует полного gc, что дорого.

5. Контроль количества потоков gc

set flag -XX:ParallelGCThreads=X повлияет на количество потоков, используемых для сбора молодого поколения и остановки фазы старого поколения. Использование большего количества потоков приведет к сокращению времени остановки и, как следствие, увеличению загрузки ЦП.

Внимание для CMS

1. минорный gc

Чем больше молодое поколение, тем меньше gc произойдет. Чем больше молодое поколение, тем дольше будут длиться циклы GC.

Размер оставшегося в живых и срок пребывания в должности

TLABS..что делать.

2. детали параллельного цикла

Параллельный цикл будет запущен, когда он будет достаточно заполнен.

Он начинается с начальной фазы маркировки, которая останавливает потоки приложения для поиска корневого объекта GC в куче.

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

Затем фаза предварительной очистки также будет выполняться одновременно, затем будет предпринята прерываемая фаза предварительной очистки, чтобы дождаться, пока молодое поколение не будет заполнено примерно на 50%, чтобы уменьшить вероятность возникновения ygc перед замечанием.

Затем фаза примечания снова остановит потоки приложения.

Фаза развертки будет меняться одновременно.

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

3. Сбой системы управления контентом

а. сбой параллельного режима

Когда возникает ygc и в старом поколении недостаточно места для продвигаемых объектов. CMS запустит полный gc.

б. продвижение не удалось из-за слишком фрагментов

Когда встречается ygc, но old-gen слишком фрагментарен для продвигаемых объектов. в середине ygc(ParNew) будет собирать и уплотнять запись старого поколения, это займет много времени, а затем одновременный отказ режима, потому что компактность стоит дорого.

в. полный сборщик мусора без одновременных сбоев

Как правило, CMS никогда не будет выполнять полную сборку мусора, ожидая одновременных сбоев или слишком фрагментов, но когда perm-gen заполнится, также потребуется полная сборка мусора. так что позаботьтесь о PerGen.

д. гонка

Когда старое поколение было заполнено на процент CMSInitiatingOccupancyFraction (по умолчанию 70%), параллельный цикл запускает гонку, CMS должен завершить сканирование и освободить объект до заполнения остатка (100% — CMSInitiatingOccupancyFraction). Если нет, произойдет сбой параллельного режима.

4. Решить проблему одновременных сбоев

а. чаще запускать параллельный цикл

Установите -XX:+UseCMSInitiatingOccupancyOnly и -XX:CMSInitiatingOccupancyFraction=N, чтобы контролировать время начала цикла.

Небольшое значение CMSInitiatingOccupancyFraction позволит начать цикл раньше. Но слишком маленькое значение позволит параллельному циклу потреблять много процессорного времени, а время запуска становится неуправляемым, когда ресурсов ЦП не хватает; и так много параллельных циклов может занять общее время паузы.

б. запускать параллельный цикл быстрее

Установите -XX:ConcGCThreads=N, чтобы управлять потоками для выполнения цикла. тем больше потоков будет иметь быстрый цикл, а также больше использование ЦП.

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

5. CMS PermGen

PermGen не будет собираться по умолчанию при использовании CMS.

Установив -XX:CMSPermGenSweepingEnable и -XX:CMSClassUnloadingEnable, потоки cms будут собирать PermGen и бесплатные метаданные класса.

6. Используйте G1

Если вы используете большую кучу и вас беспокоит проблема с фрагментами, полезно изучить G1.

Первоначально опубликовано на lysu.github.io 23 ноября 2014 г.