Java CMS GC行为

我有一个导致创建大量垃圾的应用程序。 第一个(和几乎一个)标准是低GC暂停时间。 我使用visualgc工具(和gc日志)尝试不同的GC参数。 最佳参数如下。

-XX:+ UseConcMarkSweepGC

-Xmx1172M

-Xms600M

-XX:+ UseParNewGC

-XX:新尺寸= 150M

我的应用程序在带有Java 1.6.0_21的SunOS 10上运行。 硬件是2 x CPU四核(uname -X结果是numCPU = 8)。

问题是

观察GC行为,在伊甸园空间上创建新对象,直到伊甸园已满。 当eden space full GC运行时,清除垃圾,如果对象没有死复制到Old-gen(我丢弃’从’&’到’空格),同样Old-Gen已满,GC运行与CMS并发阶段并清除旧-gen空间。 CMS的某些部分是Stop-the-world(暂停时间)。 这是一个循环。

  1. 以上场景是真的吗?
  2. 在GC清理旧的gen空间之后,没有足够的空间扩展旧的gen空间(XMS和XMS值不同)?
  3. 完全GC操作开始时? 怎么决定呢?
  4. CMS并发阶段持续时间取决于Eden空间大小,实际上我的期望是,Eden空间不会影响CMS并发阶段持续时间。 GC与CMS并发阶段的eden空间有什么关系?
  5. 还有什么建议我最小化暂停时间? 的确,对我来说最有价值的答案:)

谢谢

使用CMS时,您不能忽略幸存者空间。 CMS不是一个压缩收集器,这意味着如果你(或者JVM)错误地设置了终点,那么你将慢慢地将对象放到tenured中,这会增加tenured片段的速率,这将提升CMS被强制的时间,因为它没有足够的连续可用空间来处理从幸存者空间到终身房的促销,这将迫使完整的gc循环而没有预先警告,因此在1 STW暂停中是完整的。 这需要多长时间取决于堆的大小,但有一件事很有可能,它将比普通的伊甸园集合长几个数量级。

这里还有一些其他注意事项;

  1. STW暂停不仅来自CMS,它们也来自年轻的collections家
  2. CMS有2个STW阶段(标记和备注)和3-4个并发阶段,第1个STW阶段(标记)是严格单线程的,可能会导致问题( 此处的示例讨论)
  3. 您可以控制处理并发阶段的线程数
  4. 您需要了解对象的生存时间,这可能意味着使用-XX:+PrintTenuringDistribution或者您可以像使用visualgc一样观看它
  5. 然后,您可以使用-XX:SurvivorRatio调整此值以控制幸存者空间相对于eden和-XX:MaxTenuringThreshold的大小,以控制对象在-XX:MaxTenuringThreshold之前能够在年轻集合中生存的频率
  6. -XX:CMSInitiatingOccupancyFraction可以用来指导CMS在启动CMS阶段之前需要多长时间(出错并且你会暂停)

最终,您需要了解哪个收集器正在暂停,多长时间,多长时间以及该暂停是否有任何exception原因。 然后,您需要将其与每代的大小进行比较,以查看是否可以调整参数以最小化暂停的数量(和/或持续时间)。

请记住,由于需要长时间运行测试以确定它是否会随着时间的推移而恶化,因此可能会出现这种情况。 在没有可重复的自动化工作负载的情况下,几乎不可能得出关于您是否真正改进了事物的任何确切结论。

内部摘要信息的一个很好的来源是Jon Masamitsu的博客 。 另一个很好的演示文稿是HotSpot Java VM中的GC调优 。

最小化GC影响的最佳方法是最小化您创建的对象对象的数量。 这并不总是容易做到或总体上是最好的解决方案,但它会最大限度地减少GC暂停。

如果你不能产生更少的物体,试着让它们足够短,并且伊甸园空间足够大,以至于它们不会离开伊甸园空间。 (或者让它长寿并重复使用)

  1. 这里有三个空间值得关注,伊甸园 – >幸存者 – >终身http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html

  2. GC尝试确保在完整GC之后有足够的可用空间,并且-ms-mx选项确实控制它们的大小(以前称为-Xms-Xmx

  3. 当终身空间已满或者suvivor空间耗尽时(例如,从伊甸园空间复制的对象太多),完整的GC会启动,或者CMS desices现在是尝试并行清理的好方法。

  4. CMS仅清理终身空间。

  5. 看我以前的答案。