如何减少java并发模式失败和过度gc

如何减少java并发模式失败和过度gc,java,garbage-collection,concurrency,Java,Garbage Collection,Concurrency,在Java中,并发模式失败意味着并发收集器无法从永久和永久gen中释放足够的内存空间,必须放弃并让world gc完全停止。最终结果可能非常昂贵 我理解这个概念,但从未对 A) 什么可能导致并发模式故障和 B) 解决办法是什么 这种不清楚导致我在编写/调试代码时没有太多的提示,并且经常不得不在从Foo到Bar的性能标志之间来回切换,没有特殊的原因,只要尝试一下就可以了 我想从这里的开发人员那里了解您的经验是什么?如果您遇到这样的性能问题,原因是什么?您是如何解决的 如果您有编码建议,请不要太笼统

在Java中,并发模式失败意味着并发收集器无法从永久和永久gen中释放足够的内存空间,必须放弃并让world gc完全停止。最终结果可能非常昂贵

我理解这个概念,但从未对
A) 什么可能导致并发模式故障和
B) 解决办法是什么

这种不清楚导致我在编写/调试代码时没有太多的提示,并且经常不得不在从Foo到Bar的性能标志之间来回切换,没有特殊的原因,只要尝试一下就可以了

我想从这里的开发人员那里了解您的经验是什么?如果您遇到这样的性能问题,原因是什么?您是如何解决的

如果您有编码建议,请不要太笼统。谢谢

有时候OOM很快就死了,有时候gc周期很长(最后一次超过10小时)

在我看来,内存泄漏是你问题的根源

CMS故障不会(据我所知)导致OOM。相反,CMS失败是因为JVM需要太快地完成太多的收集,CMS无法跟上。在短时间内发生大量收集周期的一种情况是堆几乎已满

很长的GC时间听起来很奇怪。。。但理论上,如果你的机器颠簸得很厉害,这是可能的。然而,如果堆几乎满了,那么长时间重复GCs是很有可能的

您可以将GC配置为在堆1)处于最大大小,2)在完成完整GC后仍接近完全时放弃。如果您尚未这样做,请尝试这样做。它不会解决您的问题,但至少您的JVM会快速获得OOM,从而允许更快的服务重启和恢复

EDIT-执行此操作的选项是
-XX:GCHeapFreeLimit=nnn
,其中
nnn
是一个介于0和100之间的数字,给出了GC之后必须空闲的堆的最小百分比。默认值为2。该选项列在标题恰当的页面中。(这里列出了很多在Sun文档中没有出现的-XX选项。不幸的是,该页面没有提供关于这些选项实际作用的详细信息。)

您可能应该开始查看您的应用程序/Web应用程序是否存在内存泄漏。如果有,你的问题将不会消失,除非这些泄漏被发现和修复。从长远来看,摆弄热点GC选项无法修复内存泄漏。

引自

并发模式故障可以是 可以通过增加终身雇佣制来避免 生成大小或启动CMS 以较小的堆占用率收集 通过设置
CMSInitiatingOccupancyFraction
下限值

然而,如果应用程序中确实存在内存泄漏,那么您只是在争取时间

如果您需要快速重启和恢复,并且更喜欢“死快”的方法,我建议您根本不要使用CMS。我会坚持使用'-XX:+UseParallelGC'

并行垃圾收集器 (UseParallelGC)抛出一个 内存不足异常,如果 时间过长 花了一点时间收集 堆要避免此异常,您可以 增加堆的大小。你可以 同时设置参数
-XX:GCTimeLimit=时间限制
-XX:gcheapfleelimit=空间限制


关于CMS,我学到的第一件事是它比其他收集器需要更多的内存,大约25%到50%的内存是一个很好的起点。这有助于避免碎片,因为CMS不会像世界收集器那样进行任何压缩。第二,做一些有助于垃圾收集器的事情;value而不是新的整数,去掉匿名类,确保内部类不会访问不可访问的东西(在外部类中是私有的)诸如此类的东西。垃圾越少越好。FindBugs和不忽略警告将对此有很大帮助

至于调优,我发现您需要尝试以下几项:

-XX:+UseConMarkSweepGC

告诉JVM在终身发电机中使用CMS

修复堆的大小:-Xmx2048m-Xms2048m这可以防止GC执行诸如增长和收缩堆之类的操作

-XX:+UseParNewGC

在年轻一代中使用并行而不是串行采集。这将加快你的小收集,特别是如果你有一个非常大的年轻一代配置。年轻一代人数多通常是好的,但不要超过老一代人数的一半

-XX:ParallelCMSThreads=X

设置CMS在执行可以并行执行的操作时将使用的线程数

-XX:+cmsparallelremarkeabled备注默认为串行,这可以加快速度

-XX:+CMSIncrementalMode允许应用程序通过在阶段之间使用GC运行更多

-XX:+CMSIncrementalPacing允许JVM计算随时间变化的收集频率

-XX:CMSIncrementalDutyCycleMin=X执行GC所花费的最小时间量

-XX:CMSIncrementalDutyCycle=X在这%的时间内执行GC

-XX:CMSIncrementalSafetyFactor=X

我发现,如果你将它设置为基本上总是收集,你可以得到通常较低的暂停时间。由于大部分工作是并行完成的,因此最终会出现基本上规律的、可预测的暂停

-XX:CMSFullGCsBeforeCompaction=1

这一点非常重要。它告诉CMS收集器在开始新的收集之前始终完成收集。如果没有这一点,您可能会遇到这样的情况:它扔掉一堆工作,然后重新开始

-XX:+CMSClassUnloadingEnabled

默认情况下,CMS会让你的PermGen增长,直到几周后它杀死你的应用。这就停止了。如果你使用R,你的永久性激素只会增加