分享

5.CMS GC

 碧海山城 2012-12-22
参考:
http://hllvm.group./group/topic/28854

cms gc的设计文档:http://labs.oracle.com/techrep/2000/abstract-88.html



 concurrent collection的周期一般包含以下步骤:

· 中断所有application的线程运行;执行initial mark;恢复所有application的线程运行;

· 执行concurrent mark(使用一个处理器为并发工作提供服务);

· 执行concurrent pre-clean(并发预清理)(使用一个处理器为并发工作提供服务);

· 中断所有application的线程运行;执行remark;恢复所有application的线程运行;

· 执行concurrent sweep(使用一个处理器为并发工作提供服务);

· 执行concurrent reset(并发重置)(使用一个处理器为并发工作提供服务);

    

     因此CMS会有两个阶段暂停,mark和remark


1.1 CMS的开销

cms gc主要消耗的是处理器资源,他会和应用一起运行;如果想缩短暂停时间,即使在单核处理器下,也可以考虑cms,在单核模式下有incremental 模式,也能提供较好的rt

并发的线程数在1<=K<=N/4(N表示核数)

1.CMSmajor gc会有两个STW阶段,一开始会有个STW,称为初始标记阶段(initial mark pause

2.接着中间会有个并发标记的过程,Concurrent garbage collector thread会开始执行,并占用本可为application提供服务的处理器资源(对于计算密集行的应用,会有一定比例的吞吐量下降,虽然没有暂停)。在remark阶段后,是concurrent sweep阶段,用于回收那些已死亡的对象。在此阶段,Concurrent garbage collector thread又将占用那些本可为application提供服务的处理器资源。在打扫完后,Concurrent collector将进入睡眠状态,直到开始下一次的major collection

3.后面是一个比较长的STWremark pause,使用多线程标记那些在并发标记之后变为不可达的对象

1.2 CMS一些常见问题

A.为了避免Perm区满引起的full gc,建议开启CMS回收Perm区选项:
+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled


B.默认CMS是在tenured generation沾满68%的时候开始进行CMS收集,如果你的年老代增长不是那么快,并且希望降低CMS次数的话,可以适当调高此值:
-XX:CMSInitiatingOccupancyFraction=80


C.遇到两种fail引起full gcPrommotion failedConcurrent mode failed时:
Prommotion failed的日志输出大概是这样:

[ParNew (promotion failed): 320138K->320138K(353920K), 0.2365970 secs]42576.951: [CMS: 1139969K->1120688K(  166784K), 9.2214860 secs] 1458785K->1120688K(2520704K), 9.4584090 secs]  这个问题的产生是由于救助空间不够,从而向年老代转移对象,年老代没有足够的空间来容纳这些对象,导致一次full gc的产生。解决这个问题的办法有两种完全相反的倾向:增大救助空间、增大年老代或者去掉救助空间

Concurrent mode failed的日志大概是这样的

(concurrent mode failure): 1228795K->1228598K(1228800K), 7.6748280 secs] 1911483K->1681165K(1911488K), [CMS Perm : 225407K->225394K(262144K)], 7.6751800 secs]问题的产生原因是由于CMS回收年老代的速度太慢,导致年老代在CMS完成前就被沾满,引起full gc,避免这个现象的产生就是调小-XX:CMSInitiatingOccupancyFraction参数的值,让CMS更早更频繁的触发,降低年老代被沾满的可能。


D.CMS是并发的mark和sweep,没有压缩,因此会有碎片,因为一些原因,CMS会退化为Full GC,full GC时用的算法是mark-sweep-compact,但compaction是可选的,不做的话碎片化会严重些但这次full GC的暂停时间会短些;这是个取舍;

XX:+UseCMSCompactAtFullCollection:使用CMS时,顶不住要转为Full GC时压缩。 -XX:CMSFullGCsBeforeCompaction=0:上面配置开启的情况下这里设置多少次Full GC后,对年老代进行压缩。


1.3.回收时间过长而OOM

并发GC的时候,如果GC使用了98%的时间,但是只回收了2%的堆空间,就会发生OOM,这个策略是为了避免不断的处于GC中,可以通过-XX:-UseGCOverheadLimit禁用这个策略


1.4.Incremental 模式

避免并发阶段占用线程资源过多,过长,可以在young gc的时候,分阶段的尝试并发回收,对处理器资源较少的情况下比较有用

  通常,Concurrent collector在整个concurrent mark阶段,仅用一个处理器为并发工作提供服务,并且不会自愿让出占用的处理器。类似的,在concurrent sweep阶段同样仅使用一个处理器,而且也不会让出占用的处理器。这时处理器会由于application与中断时间的约束而负担过重,这种情况在仅有一或两个处理器的设备上尤为明显。I-CMS模式可解决这个问题,它将并发阶段分割成可执行的小块任务,这些任务则可被安排在两次minor pause(次要中断)之间执行。

 I-CMS使用一种名为“duty cycle(职责循环)的机制,来控制concurrent collector在自愿放弃处理器之前被允许运行的数量。duty cycle其实是两次young generation收集过程中的时间比率,以表明concurrent collector允许运行的时间。I-CMS能够根据application的行为自动计算duty cycle的时间比率(推荐这种方式),或通过命令为duty cycle设一个固定值。


6.CMS的日志

[GC [1 CMS-initial-mark: 13991K(20288K)] 14103K(22400K), 0.0023781 secs]
[GC [DefNew: 2112K->64K(2112K), 0.0837052 secs] 16103K->15476K(22400K), 0.0838519 secs]
...
[GC [DefNew: 2077K->63K(2112K), 0.0126205 secs] 17552K->15855K(22400K), 0.0127482 secs]
[CMS-concurrent-mark: 0.267/0.374 secs]
[GC [DefNew: 2111K->64K(2112K), 0.0190851 secs] 17903K->16154K(22400K), 0.0191903 secs]
[CMS-concurrent-preclean: 0.044/0.064 secs]
[GC [1 CMS-remark: 16090K(20288K)] 17242K(22400K), 0.0210460 secs]
[GC [DefNew: 2112K->63K(2112K), 0.0716116 secs] 18177K->17382K(22400K), 0.0718204 secs]
[GC [DefNew: 2111K->63K(2112K), 0.0830392 secs] 19363K->18757K(22400K), 0.0832943 secs]
...
[GC [DefNew: 2111K->0K(2112K), 0.0035190 secs] 17527K->15479K(22400K), 0.0036052 secs]
[CMS-concurrent-sweep: 0.291/0.662 secs]
[GC [DefNew: 2048K->0K(2112K), 0.0013347 secs] 17527K->15479K(27912K), 0.0014231 secs]
[CMS-concurrent-reset: 0.016/0.016 secs]
[GC [DefNew: 2048K->1K(2112K), 0.0013936 secs] 17527K->15479K(27912K), 0.0014814 secs]


CMS-initial-mark:表明concurrent collection cycle的启动,CMS-concurrent-mark:表明concurrent marking phase的结束,CMS-concurrent-sweep:标记concurrent sweeping phase的结束。CMS-concurrent-preclean:表明之前没有讨论的precleaning phasePrecleaning,它是一项为标记阶段CMS-remark提供的准备工作,而且能并发完成。最后阶段由CMS-concurrent-reset来定义,它是下一次concurrent collection的准备过程。


 initial mark pause所用的时间相比minor collection pause来说通常很短。而concurrent phases的所用的时间(concurrent mark, concurrent precleaning, concurrent sweep)比起minor collection pause可能相对较长,但application不会在concurrent phases被中断。remark pause则被application的特殊细节(比如,高频度的修改对象便可使中断增加),以及自最后一次进行minor collection的时间所影响(换言之,young generation中的对象越多就越可能使中断增加)。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多