我有一个导致产生大量垃圾的应用程序。第一个(和几乎一个)标准是低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并发阶段并且清除老一代的空间。 CMS的某些部分是Stop-the-world(暂停时间)。这是一个循环。
由于
答案 0 :(得分:10)
使用CMS时,您不能忽略幸存者空间。 CMS不是一个压缩收集器,这意味着如果你(或者JVM)得到了错误的终点,那么你将慢慢地将对象放到tenured中,这会增加tenured片段的速率,这将提升CMS被强制的时间,因为它没有足够的连续可用空间来处理从幸存者空间到终身房的促销,这将迫使完整的gc循环而没有预先警告,因此在1 STW暂停中是完整的。这需要多长时间取决于堆的大小,但有一件事很有可能,它将比普通的伊甸园集合长几个数量级。
此处还有一些其他注意事项;
-XX:+PrintTenuringDistribution
或者您可以像使用visualgc一样观看-XX:SurvivorRatio
调整此值以控制相对于伊甸园的幸存者空间的大小,并控制-XX:MaxTenuringThreshold
以控制对象在年轻收藏之前能够存活的频率-XX:CMSInitiatingOccupancyFraction
可用于指导CMS在启动CMS阶段之前需要多长时间才能完成(出错并且你会暂停)最终,您需要了解哪个收集器正在暂停,多长时间,多长时间以及该暂停是否有任何异常原因。然后,您需要将其与每一代的大小进行比较,以查看是否可以调整参数以最小化暂停的数量(和/或持续时间)。
请记住,由于需要长时间运行测试以确定它是否会随着时间的推移而恶化,因此可能会出现这种情况。同样没有可重复的自动化工作量,几乎不可能得出关于你是否真正改进过的任何确切结论。
关于内部的摘要信息的一个很好的来源是Jon Masamitsu's blog。另一个很好的演讲是GC Tuning in the HotSpot Java VM。
答案 1 :(得分:2)
最小化GC影响的最佳方法是尽量减少您创建的对象对象的数量。这并不总是容易做到或总体上是最佳解决方案,但它会最大限度地减少GC暂停。
如果你不能产生更少的物体,试着让它们足够短,并且伊甸园空间足够大,以至于它们不会离开伊甸园空间。 (或者让它长寿并重复使用)
这里有三个空间需要担心,eden - >幸存者 - >终身http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html
GC尝试确保完整GC后有足够的可用空间,-ms
和-mx
选项可以控制它们的大小(以前称为-Xms
和-Xmx
)
当终身空间已满或者suvivor空间耗尽时(例如,从伊甸园空间复制了太多对象),完整的GC会启动,或者CMS desices现在是尝试做的好瓷砖并发清理。
CMS仅清理终身空间。
请参阅我以前的答案。