Проблемы с сборкой мусора 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]
Процесс preclean продолжает прерываться непрерывно. Я попытался настроить 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
Кажется, что одновременный-abortable-preclean никогда не будет работать. Я прочитал https://blogs.oracle.com/jonthecollector/entry/did_you_know, в котором было предложено включить CMSScavengeBeforeRemark, но побочные эффекты приостановки не казались идеальными. Может ли кто-нибудь предложить какие-либо предложения?
Также мне было интересно, есть ли у кого-то хорошая ссылка для grokking журналов CMS GC, в частности, этой строки:
[1 CMS-remark: 16015K(393216K)] 71979K(511232K), 0.0746640 secs]
Непонятно, в каких областях памяти эти числа ссылаются.
Изменить Найдите ссылку на http://www.sun.com/bigadmin/content/submitted/cms_gc_logs.jsp
Ответы
Ответ 1
[Times: user = 0.00 sys = 0.01, real = 5.09 secs]
Я бы попытался выяснить, почему 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
то проверьте, воспроизводится ли проблема и постоянно ли настраивается один параметр.
Ответ 2
Как уже упоминалось, первым шагом было бы увеличить CMSInitiatingOccupancyFraction.
В качестве второго шага я использую флаг -XX:-PrintTenuringDistribution
и убедитесь, что нет преждевременной рекламы от молодого поколения до старого. Это приведет к привязке старых к молодым, что может привести к более длительной прерывистой фазе preclean.
Если есть такая преждевременная акция, попробуйте отрегулировать соотношение между эденом и пространствами вышедших.
Ответ 3
Существует хорошее объяснение здесь об этом явлении:
Цитата:
Итак, когда нагрузка системы светлая (значит, не будет minor gc), preleaning всегда будет тайм-аут, и полный gc всегда будет потерпеть неудачу. cpu - это отходы.
Это не подведет. Он будет менее параллельным (т.е. Менее эффективным и будет имеют более длительное время паузы, для меньшей работы).
Итак, в целом: это, по-видимому, нормальная работа - поток просто ждет, когда младший GC произойдет в течение 5 секунд, но нет большой проблемы, когда этого не происходит: JVM выбирает другую (менее эффективную) стратегия продолжения работы с GC.