当老年代为空时,JVM运行旧代垃圾收集。

4

我有一个Clojure应用正在运行,对于大堆内存分配会产生很多的内存抖动,因此已经适当设置了JVM选项:

-Xmx13g -XX:+UseConcMarkSweepGC -XX:NewSize=10G -server -XX:+UseParNewGC

大多数情况下,这种方法都有效,可以避免新生代溢出到旧生代(有时仍会到幸存者代,但不总是)。但有时我们会看到像图片中所示的情况,即当新生代满时,JVM会非常努力地运行CMS / old gen垃圾收集。据我了解,这应该由新生代垃圾收集器处理。

enter image description here

两个问题。为什么旧生代垃圾收集器在旧生代几乎为空但新生代有东西时仍在运行?还有没有进一步的调整可以减少这不可避免地引起的GC暂停/减速?

预计时间:在OpenJDK 8上运行。

预计时间2:GC日志:https://gist.github.com/gworley3/6abb9ab52320c6cbd508


3
我看不到任何迹象表明旧空间正在进行垃圾回收。 - AppX
基于观察到大量的CPU时间被用于运行CMS(请参见图像中的垃圾回收CPU时间图表)。 - Gordon Seidoh Worley
1
你应该启用GC日志记录并发布一个相当大的样本。你还应该指定你正在使用哪个JVM版本。此外,你的新生代大小似乎过大。 - the8472
抱歉,我本来想包含这个信息的:OpenJDK 8。此外,新一代大小需要那么大,因为代码最终会为偶尔的短暂请求分配7到8 GB的RAM用于数据结构。 - Gordon Seidoh Worley
你还没有包括GC日志。 - the8472
显示剩余2条评论
1个回答

2

简短回答:

CMS在没有必要的情况下花费太多时间扫描近10GB的Young Gen。您可以通过添加以下选项来防止CMS收集器不必要地运行:

‑XX:+UseCMSInitiatingOccupancyOnly ‑XX:CMSInitiatingOccupancyFraction=<K>

其中K是占用的Old Gen空间的任意分数。

详细回答:

参考Oracle CMS文档

CMS收集器在并发收集周期中暂停应用程序两次。第一次暂停是为了标记从根(例如,应用程序线程堆栈和寄存器、静态对象等)和堆的其他位置(例如,young generation)直接可达的对象。这个第一次暂停被称为初始标记暂停。第二个暂停发生在并发跟踪阶段的结束,找到了由于应用程序线程在CMS收集器完成跟踪该对象后更新该对象的引用而被并发跟踪遗漏的对象。这个第二次暂停被称为重新标记暂停。

CMS在两个stop-the-world暂停期间每次都会扫描Young Gen进行标记。查看日志的前三行,您可以看到初始标记需要5秒钟,然后是ParNew,之后又需要0.25秒。重新标记也有类似的时间减少。

<190>1 2015-12-18T08:44:54.194216+00:00 host app web.1 - [GC[YG occupancy: 489826 K (9437184 K)][Rescan (parallel) , 0.2520950 secs][weak refs processing, 0.0000180 secs][scrub string table, 0.0008190 secs] [1 CMS-remark: 64504K(107240K)] 554330K(9544424K), 0.2530410 secs] [Times: user=1.95 sys=0.02, real=0.25 secs]

<190>1 2015-12-18T08:44:49.937257+00:00 host app web.1 - [GC[ParNew:   8418004K->93508K(9437184K), 0.0488580 secs] 8482343K->158013K(9544424K), 0.0489980 secs] [Times: user=0.33 sys=0.00, real=0.05 secs]

<190>1 2015-12-18T08:44:48.651086+00:00 host app web.1 - [GC [1 CMS-initial-mark: 64339K(107240K)] 7800216K(9544424K), 5.0756660 secs] [Times: user=5.08 sys=0.00, real=5.08 secs]

每个CMS循环后,您的旧代空间几乎不会被减少,因此这种开销肯定不值得。降低CMS循环的频率是一种可能的解决方案。


这似乎解决了问题。将占用分数设置为70效果很好。感谢您对CMS工作方式的深入洞察:我曾经认为它只会在老年代有东西时才运行,就像串行GC一样。 - Gordon Seidoh Worley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接