jim*_*imx 44 java concurrency garbage-collection
在Java中,并发模式失败意味着并发收集器无法释放足够的内存空间形成终身和永久性,并且必须放弃并让完全停止世界的 gc开始.最终结果可能非常昂贵.
我理解这个概念,但从未对
A)有什么可能导致并发模式失败以及
B)什么是解决方案有一个很好的全面理解.
这种不清楚导致我编写/调试代码而没有太多提示,并且经常不得不在没有特殊原因的情况下从Foo到Bar那些性能标记,只需要尝试.
我想向开发人员学习一下你的经历如何?如果您遇到此类性能问题,原因是什么以及您如何解决它?
如果您有编码建议,请不要太笼统.谢谢!
小智 23
我学到的关于CMS的第一件事就是它比其他收藏家需要更多的内存,大约25%到50%是一个很好的起点.这可以帮助您避免碎片,因为CMS不会像世界收藏家那样做任何压缩.第二,做有助于垃圾收集者的事情; Integer.valueOf而不是新的Integer,摆脱匿名类,确保内部类不访问不可访问的东西(在外部类中是私有的)这样的东西.垃圾越少越好.FindBugs而不是忽略警告将对此有很大帮助.
至于调优,我发现你需要尝试几件事:
-XX:+ UseConcMarkSweepGC
告诉JVM在tenured gen中使用CMS.
修复堆的大小:-Xmx2048m -Xms2048m这可以防止GC执行诸如增长和收缩堆之类的操作.
-XX:+ UseParNewGC
在年轻一代使用并行而不是串行集合.这将加速你的次要收藏,特别是如果你配置了一个非常大的年轻人.一个大的年轻一代通常是好的,但不超过旧的一半大小的一半.
-XX:ParallelCMSThreads = X
设置CMS在执行可以并行执行的操作时将使用的线程数.
-XX:+ CMSParallelRemarkEnabled备注默认是串行的,这可以加快你的速度.
-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成长,直到它从现在开始几周内杀死你的应用程序.这样就可以了.如果你使用Reflection,或者滥用String.intern,或者使用类加载器或其他一些东西做坏事,你的PermGen只会增长.
幸存者比率和持久时间也可以使用,具体取决于您是否拥有长期或短期物体,以及您可以使用的幸存者空间之间复制多少物体.如果你知道你的所有物体都要留在那里,你可以配置零大小的幸存者空间,任何幸存下来的年轻人都可以立即终身.
fgl*_*lez 12
通过设置
CMSInitiatingOccupancyFraction
较低的值,可以通过增加tenured generation大小或以较小的堆占用率启动CMS集合来避免并发模式故障
但是,如果您的应用程序中确实存在内存泄漏,那么您只是在购买时间.
如果您需要快速重启和恢复并且更喜欢"快死"的方法,我建议您根本不使用CMS.我会坚持'-XX:+ UseParallelGC'.
如果花费过多的时间来收集少量的堆,则并行垃圾收集器(UseParallelGC)会抛出内存不足的异常.要避免此异常,可以增加堆的大小.您也可以设置参数
-XX:GCTimeLimit=time-limit
和-XX:GCHeapFreeLimit=space-limit
有时 OOM 很快就会被杀死,有时会遭受很长的 GC 周期(上次超过 10 小时)。
在我看来,内存泄漏是问题的根源。
CMS 故障不会(据我所知)导致 OOM。相反,CMS 失败的发生是因为 JVM 需要太快地执行太多收集,而 CMS 无法跟上。短时间内发生大量收集周期的一种情况是堆几乎已满。
很长的 GC 时间听起来很奇怪……但如果你的机器运行得非常厉害,理论上是可能的。然而,如果您的堆几乎已满,则很可能会出现长时间的重复 GC。
您可以将 GC 配置为在堆 1) 达到最大大小且 2) 完整 GC 完成后仍接近满时放弃。如果您还没有这样做,请尝试这样做。它不会解决你的问题,但至少你的 JVM 会很快出现 OOM,从而允许更快的服务重启和恢复。
编辑- 执行此操作的选项是-XX:GCHeapFreeLimit=nnn
0nnn
到 100 之间的数字,给出 GC 后必须空闲的堆的最小百分比。默认值为 2。该选项列在标题为“Java 6 JVM 的 -XX 选项的最完整列表”页面中。(那里列出了许多未出现在 Sun 文档中的 -XX 选项。不幸的是,该页面提供的有关这些选项实际用途的详细信息很少。)
您可能应该开始查看您的应用程序/网络应用程序是否存在内存泄漏。如果有,除非找到并修复这些泄漏,否则您的问题将不会消失。从长远来看,摆弄 Hotspot GC 选项并不能解决内存泄漏问题。