Проблемы сбора мусора в JVM CMS

Я вижу следующие признаки в файле журнала GC приложения с коллектором Concurrent Mark-Sweep:

4031.248: [CMS-concurrent-preclean-start]
4031.250: [CMS-concurrent-preclean: 0.002/0.002 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
4031.250: [CMS-concurrent-abortable-preclean-start]
 CMS: abort preclean due to time 4036.346: [CMS-concurrent-abortable-preclean: 0.159/5.096 secs] [Times: user=0.00 sys=0.01, real=5.09 secs] 
4036.346: [GC[YG occupancy: 55964 K (118016 K)]4036.347: [Rescan (parallel) , 0.0641200 secs]4036.411: [weak refs processing, 0.0001300 secs]4036.411: [class unloading, 0.0041590 secs]4036.415: [scrub symbol & string tables, 0.0053220 secs] [1 CMS-remark: 16015K(393216K)] 71979K(511232K), 0.0746640 secs] [Times: user=0.08 sys=0.00, real=0.08 secs] 

Пречистый процесс постоянно прерывается. Я попытался настроить CMSMaxAbortablePrecleanTime до 15 секунд, по умолчанию 5, но это не помогло. Текущие параметры JVM следующие:

Djava.awt.headless=true
 -Xms512m
 -Xmx512m
 -Xmn128m
 -XX:MaxPermSize=128m
 -XX:+HeapDumpOnOutOfMemoryError
 -XX:+UseParNewGC
 -XX:+UseConcMarkSweepGC
 -XX:BiasedLockingStartupDelay=0
 -XX:+DoEscapeAnalysis
 -XX:+UseBiasedLocking
 -XX:+EliminateLocks
 -XX:+CMSParallelRemarkEnabled
 -verbose:gc
 -XX:+PrintGCTimeStamps
 -XX:+PrintGCDetails
 -XX:+PrintHeapAtGC
 -Xloggc:gc.log
 -XX:+CMSClassUnloadingEnabled
 -XX:+CMSPermGenPrecleaningEnabled
 -XX:CMSInitiatingOccupancyFraction=50
 -XX:ReservedCodeCacheSize=64m
 -Dnetworkaddress.cache.ttl=30
 -Xss128k

Кажется, что concurrent-abortable-preclean никогда не получает шанс бежать. Я прочитал https://blogs.oracle.com/jonthecollector/entry/did_you_know котором предлагалось включить CMSScavengeBeforeRemark, но побочные эффекты приостановки не казались идеальными. Может ли кто-нибудь предложить какие-либо предложения?

Кроме того, мне было интересно, есть ли у кого-нибудь хорошая справка для создания журналов CMS GC, в частности, этой строки:

[1 CMS-remark: 16015K(393216K)] 71979K(511232K), 0.0746640 secs]

Не ясно, на какие области памяти ссылаются эти цифры.Изменить Найдено ссылку на этот http://www.sun.com/bigadmin/content/submitted/cms_gc_logs.jsp

4 ответа

Как уже упоминалось, первым шагом было бы увеличение CMSInitiatingOccupancyFraction.

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

[Время: пользователь =0,00 сис =0,01, реальное =5,09 с]

Я бы попробовал выяснить почему CMS-concurrent-abortable-preclean-start не получает ни пользовательское, ни системное процессорное время за 5 секунд.

Мое предложение начинается с "чистых" флагов запуска JVM CMS, таких как

-Djava.awt.headless=true
-Xms512m
-Xmx512m
-Xmn128m
-Xss128k
-XX:MaxPermSize=128m
-XX:+UseConcMarkSweepGC
-XX:+HeapDumpOnOutOfMemoryError
-Xloggc:gc.log
-XX:+PrintGCTimeStamps
-XX:+PrintGCDetails
-XX:+PrintHeapAtGC

затем проверьте, воспроизводится ли проблема, и продолжайте настраивать один параметр за раз.

Здесь есть хорошее объяснение этому феномену:

Цитата:

Таким образом, когда загрузка системы мала (что означает, что не будет никакого незначительного gc), предварительная очистка будет всегда истекать, и полный gc всегда будет терпеть неудачу. процессор это отходы.

Это не подведет. Он будет менее параллельным (то есть менее эффективным и будет иметь более длительное время паузы для меньшей работы).

Итак, в целом: это кажется нормальной операцией - поток просто ждет, пока второстепенный GC произойдет в течение 5 секунд, но нет большой проблемы, когда этого не происходит: JVM выбирает другую (менее эффективную) стратегию для продолжения с GC.

Для службы, которую я использую, я добавил:

      -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=80

Это настраивает JVM на запуск маркировки только после заполнения 80%, и стоит попробовать.

Другие вопросы по тегам