代码之家  ›  专栏  ›  技术社区  ›  jimx

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

  •  43
  • jimx  · 技术社区  · 16 年前

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


    A) 什么会导致并发模式故障和
    B) 解决办法是什么?。

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

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

    4 回复  |  直到 12 年前
        1
  •  23
  •   Community Mohan Dere    5 年前

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

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

    告诉JVM在永久gen中使用CMS。

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

    -二十: +UseParNewGC使用

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

    -二十: 并行CMSThreads=X

    -二十: +CMSParallelRemarkEnabled默认为serial,这样可以加快速度。

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

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

    -二十: CMSIncrementalDutyCycle=X从这%的时间执行GC开始

    -二十: CMSIncrementalSafetyFactor=X

    -二十: CMSFullGCsBeforeCompaction=1

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

    默认情况下,CMS会让你的PermGen增长,直到它在几周后杀死你的应用程序。这就停止了。如果你利用反射,或者滥用反射,你的永久性头发只会增长String.实习生,或者用类加载器做一些不好的事情,或者其他一些事情。

    幸存者比率和保存时间也可以使用,这取决于你是否有长寿命的对象,以及你可以在幸存者空间之间复制多少对象。如果你知道你的所有对象都会留下来,你可以配置零大小的幸存者空间,任何幸存下来的年轻一代收集将立即终身。

        2
  •  12
  •   fglez    11 年前

    引自 "Understanding Concurrent Mark Sweep Garbage Collector Logs"

    通过增加终身监禁来避免 以较低的堆占用率收集 通过设置 CMSInitiatingOccupancyFraction 到 下限值

    但是,如果应用程序中确实存在内存泄漏,那么这只是在争取时间。

    如果你需要快速重新启动和恢复,并喜欢一个'死快'的方法,我建议不要使用CMS在所有。我会坚持'-XX:+usepallelgc'。

    "Garbage Collector Ergonomics"

    并行垃圾收集器 如果 时间过长 收集少量的 堆。要避免此异常,您可以 增加堆的大小。你可以 -XX:GCTimeLimit=time-limit -XX:GCHeapFreeLimit=space-limit

        3
  •  4
  •   Stephen C    16 年前

    有时很快就被杀了,有时经历了很长的gc期(最后一次超过10个小时)。

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

    很长的时间听起来很奇怪。。。但如果你的机器在剧烈地摇晃,理论上是可能的。然而,如果你的堆快满了,那么长时间的重复GCs是很有可能的。

    编辑 -这样做的选择是 -XX:GCHeapFreeLimit=nnn nnn 是一个介于0和100之间的数字,给出GC之后必须空闲的堆的最小百分比。默认值为2。该选项列在标题恰当的 "The most complete list of -XX options for Java 6 JVM" 第页。(这里列出了许多Sun文档中没有的-XX选项。不幸的是,该页面没有提供有关选项实际作用的详细信息。)

        4
  •  0
  •   Brian Mains    13 年前

    我发现使用 -XX:PretenureSizeThreshold=1m 使“大”对象立即转到永久空间大大减少了我的年轻GC和并发模式失败,因为它往往不会尝试转储年轻+1幸存者的数据量( xmn=1536m survivorratio=3 maxTenuringThreashould=5 )在整个CMS循环完成之前。是的,我的幸存者空间很大,但是大约每两天就有一次应用程序需要它(我们每天为一个应用程序运行12个应用程序服务器)。