Java CMS GC行为
问题内容:
我有一个导致创建大量垃圾的应用程序。第一个(也是几乎一个)标准是GC暂停时间短。我使用visualgc工具(和gc日志)尝试了不同的GC参数。最佳参数如下。
-XX:+ UseConcMarkSweepGC
-Xmx1172M
-Xms600M
-XX:+ UseParNewGC
-XX:NewSize = 150M
我的应用程序在带有Java 1.6.0_21的SunOS 10上运行。硬件为2 x CPU四核(uname -X结果为numCPU = 8)。
问题是
观察GC行为,在eden空间上创建新对象,直到eden满为止。当eden space满GC运行时,清除垃圾,如果对象没有死拷贝到Old-gen(我丢弃“ from”和“ to”空间),类似Old-Gen已满,GC在CMS并发阶段运行并清除Old -gen空间。CMS的某些部分是“世界停止”(暂停时间)。这是一个循环。
- 以上场景是真的吗?
- GC清除旧空间后,没有足够的空间扩展旧空间(XMS和XMS值不同)?
- 何时启动完全GC操作?如何决定呢?
- CMS并发阶段持续时间取决于Eden空间大小,实际上我的期望是,Eden空间不会影响CMS并发阶段持续时间。CMS并发阶段中与伊甸园空间有关的GC发生了什么?
- 还有什么建议对我最大程度地减少了暂停时间?确实,对我来说最有价值的答案:)
谢谢
问题答案:
使用CMS时,您不能仅仅忽略幸存者空间。CMS不是紧凑的收集器,这意味着如果您(或JVM)错误地确定了使用期限阈值,则您将缓慢地将对象放空到使用期限,这将增加使用期限片段的比率,这将延长强制执行CMS的时间,因为没有足够的连续可用空间来处理从幸存者空间升为保有权的提升,这将强制执行完整的gc周期而没有提前警告,因此这是1 STW暂停中的全部。这需要多长时间取决于堆的大小,但很可能会发生一件事,它将比正常的eden集合长几个数量级。
这里还有其他一些注意事项;
- STW暂停不仅来自CMS,而且也来自年轻的一代收藏家
- CMS有2个STW阶段(标记,备注)和3-4并发阶段,第一阶段STW(标记)严格单线程这可能会导致问题(样品讨论这个在这里)
- 您可以控制处理并发阶段的线程数
- 您需要了解物体可以生存多长时间,这可能意味着要使用它,
-XX:+PrintTenuringDistribution
或者可以像完成操作一样使用visualgc观看它 - 然后,您可以对其进行调整,
-XX:SurvivorRatio
以控制相对于伊甸园的幸存者空间的大小,并-XX:MaxTenuringThreshold
控制对象在使用年限之前可以幸存的频率 -XX:CMSInitiatingOccupancyFraction
可以用来指导CMS在开始CMS阶段之前需要达到多满(输入错误,将会严重停顿)
最终,您需要了解哪个收集器正在暂停,暂停多长时间,暂停多长时间以及是否有任何异常原因导致暂停。然后,您需要将此值与每一代的大小进行比较,以查看是否可以调整参数,以最大程度地减少暂停次数(和/或持续时间)。
请记住,由于需要长时间运行的测试以查看其是否随着时间的推移而恶化,因此这可能会浪费时间。而且,由于没有可重复的自动化工作负载,因此几乎不可能就您是否确实在改进方面得出任何肯定的结论。