低暂停收集器 - 并发模式故障

时间:2012-06-22 11:00:14

标签: java garbage-collection

我们正在使用我们的其中一个应用程序遇到问题。

VM配置如下

-XX:MaxPermSize = 300M -Xms2560M -Xmx2560M -Xloggc:/app/log/gc-admin-20120619-123754.log -verbose:gc -XX:+ PrintGCTimeStamps -XX:+ PrintGCDetails -XX:+ UseConcMarkSweepGC - XX:CMSInitiatingOccupancyFraction = 80 -XX:+ DisableExplicitGC -XX:CMSMaxAbortablePrecleanTime = 8000

我错过并将应用的两个选项是 XX:PermSize - 应与MaxPermSize相同(推荐) 当使用CMSInitiatingOccupancyFraction时,UseCMSInitiatingOccupancyOnly,否则您指定的值不会粘住!!

然而,由于pipleline中的这些变化我不太自信,它将解决我的问题。

我看到并发模式失败,但是当失败发生时,停止世界收集需要永恒。目前我有点困惑为什么!!

以下是一些示例

  

168427.476:[GC [1 CMS-initial-mark:2135988K(2578880K)] 2141041K(2617216K),3.1029210 secs] [次:用户= 0.02 sys = 0.01,real = 3.10 secs]   168430.596:[CMS-concurrent-mark-start]   168441.309:[GC 168441.309:[ParNew:36520K-> 36520K(38336K),0.0000210 secs] 168441.309:[CMS168747.453:[CMS-concurrent-mark:309.313 / 316.857 secs] [次:用户= 5.75 sys = 2.89,真实= 316.81秒]    (并发模式失败):2561882K-> 1310927K(2578880K),767.0309740秒] 2598402K-> 1310927K(2617216K),[CMS Perm:96774K-> 96171K(158792K)],767.0379030秒] [时间:用户= 3.87 sys = 5.06,real = 766.92 secs]

整个STW集合让我担心的是时间766.92secs,但只有“user = 3.87 sys = 5.06”的CPU时间,那么剩下的时间里会发生什么?这是我很困惑的地方,我无法想象停止应用程序中的所有线程需要那么久!吵架也许??

  

169545.325:[GC [1 CMS-initial-mark:2141069K(2578880K)] 2166025K(2617216K),0.0530140 secs] [次:用户= 0.05 sys = 0.00,real = 0.06 secs]   169545.379:[CMS-concurrent-mark-start]   169558.635:[CMS-concurrent-mark:10.407 / 13.256 secs] [次:用户= 7.58 sys = 0.53,real = 13.25 secs]   169558.635:[CMS-concurrent-preclean-start]   169558.684:[CMS-concurrent-preclean:0.048 / 0.048 secs] [次:用户= 0.01 sys = 0.00,real = 0.05 secs]   169558.684:[CMS-concurrent-abortable-preclean-start]   169560.544:[GC 169560.544:[ParNew169560.605:[CMS-concurrent-abortable-preclean:0.210 / 1.921 secs] [次:用户= 0.93 sys = 0.05,real = 1.92 secs]   169560.846:[GC [YG占有率:1906 K(38336 K)] 169560.846:[重新扫描(平行),0.0046910秒] 169560.851:[弱参考处理,0.0000990秒] [1 CMS-备注:2350428K(2578880K)] 2352335K(2617216K) ),0.0048570秒] [时间:用户= 0.01 sys = 0.00,实际= 0.01秒]   169560.853:[CMS-concurrent-sweep-start]   169568.204:[CMS-concurrent-sweep:7.351 / 7.351 secs] [次:用户= 0.91 sys = 0.09,real = 7.34 secs]   169568.204:[CMS-concurrent-reset-start]   169568.211:[CMS-concurrent-reset:0.007 / 0.007 secs] [次:用户= 0.01 sys = 0.00,实际= 0.01秒]

这个没有问题

  

252247.318:[GC [1 CMS-initial-mark:2069401K(2578880K)] 2075094K(2617216K),1.5311840 secs] [次:用户= 0.01 sys = 0.00,real = 1.53 secs]   252248.849:[CMS-concurrent-mark-start]   252350.336:[GC 252350.336:[ParNew:20984K-> 4222K(38336K),12.2251190 secs] 252362.561:[CMS252520.780:[CMS-concurrent-mark:161.376 / 271.922 secs] [次:用户= 12.56 sys = 1.72,真实= 271.89秒]    (并发模式失败):2232372K-> 1061586K(2578880K),407.2310250秒] 2240205K-> 1061586K(2617216K),[CMS Perm:97525K-> 97381K(160480K)],419.4586450 secs] [次:用户= 4.23 sys = 2.99,real = 419.39 secs]

然后是另一个大佬“Times:user = 4.23 sys = 2.99,real = 419.39 secs”。 CPU时间很小“user = 4.23 sys = 2.99”,但总时间为“419.39”。什么可能导致VM挂起这么久?理想情况下,应在10秒内收集STW集合中的2.5g !!

我要降低门槛CMSInitiatingOccupancyFraction,但我不认为收集时间会有所帮助!有些收藏品运行顺畅,有些收藏品不像我说的那样,当我完全停止世界时,它让我担心的时机。

我读过 https://blogs.oracle.com/jonthecollector/entry/what_the_heck_s_a

我们正在使用jdk6。

以前有人经历过类似的事吗?

3 个答案:

答案 0 :(得分:2)

正如您所观察到的,当并发模式失败时,会回落到世界各地。我的理解是,这个可以使用mark-sweep-compact收集器而不是更有效的复制收集器来完成。

这并不能完全解释为什么收藏需要这么长时间。但是,虚拟机颠簸是一个看似合理的理论,您的证据支持这一点......但您需要对VM交换/寻呼速率进行一些操作系统级别的测量才能确定。 (如果JVM会导致颠簸,那么当堆已满时,在完全垃圾收集期间最有可能是最糟糕的。)

回到导致并发模式失败的原因,您链接的博客说明了最有可能发生的事情:

  • 您的堆已满或
  • 对象分配率太高,或
  • 对象分配率太可变,或
  • 以上的一些组合。

建议的解决方案是:

  • 增加堆大小。
  • 降低CMSInitiatingOccupancyFraction值
  • 增加CMSIncrementalSafetyFactor值

另一个是切换到吞吐量收集器,并且偶尔遭遇" longish"当它完整收集时暂停。

如果问题是虚拟机颠簸,那么你就是在一块坚硬的地方之间。您已经相对于计算机或虚拟机可用的物理RAM量过度分配了虚拟内存。您可以选择为机器/虚拟机提供更多RAM,或者通过减少堆大小,停止服务和应用程序等来减少系统的虚拟内存使用量。

(请注意,无论您是否使用虚拟化,都可能发生虚拟内存抖动。就像虚拟化一样,过度分配内存的诱惑力更强......)

答案 1 :(得分:1)

您的应用程序是否在虚拟机上运行?

解释可能是您的主机过载或交换,这会阻止VM工作并看到发生的事情。

答案 2 :(得分:0)

永久代(PermSize)用于反映VM本身,例如类对象和方法对象。这些反射物体直接分配到永久世代中,并且其尺寸独立于其他世代。通常,可以忽略此代的大小,因为默认大小足够。但是,加载许多类的程序可能需要更大的永久代。

默认情况下,MaxPermSize对于-client为32mb,对于-server为64mb。但是,如果不同时设置PermSizeMaxPermSize,则除非需要,否则整个堆不会增加。当您设置PermSizeMaxPermSize时,例如192mb,额外的堆空间将在启动时分配,并将保持分配。

尝试调整两个VM参数,它可能会解决您的问题。

-XX:PermSize=300m -XX:MaxPermSize=300m