问题描述
在Java中,并发模式失败意味着并发收集器未能从tenured和permanent gen中释放足够的内存空间,不得不放弃并让完整的stop-the-world gc启动in. 最终结果可能会非常昂贵.
In Java, the concurrent mode failure means that the concurrent collector failed to free up enough memory space form tenured and permanent gen and has to give up and let the full stop-the-world gc kicks in. The end result could be very expensive.
我了解这个概念,但对
没有很好的全面了解A) 什么可能导致并发模式失败和
B) 解决方案是什么?
I understand this concept but never had a good comprehensive understanding of
A) what could cause a concurrent mode failure and
B) what's the solution?.
这种不清楚导致我在没有太多提示的情况下编写/调试代码,并且经常不得不在没有特殊原因的情况下绕过从 Foo 到 Bar 的那些性能标志,只需要尝试一下.
This sort of unclearness leads me to write/debug code without much of hints in mind and often has to shop around those performance flags from Foo to Bar without particular reasons, just have to try.
我想在这里向开发人员了解您的体验如何?如果您遇到过这样的性能问题,原因是什么以及您是如何解决的?
I'd like to learn from developers here how your experience is? If you had encountered such performance issue, what was the cause and how you addressed it?
如果您有编码建议,请不要过于笼统.谢谢!
If you have coding recommendations, please don't be too general. Thanks!
推荐答案
我了解到的关于 CMS 的第一件事是它比其他收集器需要更多的内存,大约多 25% 到 50% 是一个很好的起点.这可以帮助您避免碎片,因为 CMS 不会像世界收集器那样进行任何压缩.第二,做对垃圾收集器有帮助的事情;Integer.valueOf 而不是 new Integer,摆脱匿名类,确保内部类不会访问不可访问的东西(外部类中的私有)之类的东西.垃圾越少越好.FindBugs 并且不忽略警告将对此有很大帮助.
The first thing about CMS that I have learned is it needs more memory than the other collectors, about 25 to 50% more is a good starting point. This helps you avoid fragmentation, since CMS does not do any compaction like the stop the world collectors would. Second, do things that help the garbage collector; Integer.valueOf instead of new Integer, get rid of anonymous classes, make sure inner classes are not accessing inaccessible things (private in the outer class) stuff like that. The less garbage the better. FindBugs and not ignoring warnings will help a lot with this.
至于调优,我发现你需要尝试几件事:
As far as tuning, I have found that you need to try several things:
-XX:+UseConcMarkSweepGC
-XX:+UseConcMarkSweepGC
告诉 JVM 在tenured gen 中使用 CMS.
Tells JVM to use CMS in tenured gen.
修复堆的大小:-Xmx2048m -Xms2048m 这可以防止 GC 执行诸如增大和缩小堆之类的操作.
Fix the size of your heap: -Xmx2048m -Xms2048m This prevents GC from having to do things like grow and shrink the heap.
-XX:+UseParNewGC
-XX:+UseParNewGC
在年轻代中使用并行而不是串行收集.这将加快您的次要集合,特别是如果您配置了非常大的年轻一代.一个大的年轻代通常是好的,但不要超过老一代的一半.
use parallel instead of serial collection in the young generation. This will speed up your minor collections, especially if you have a very large young gen configured. A large young generation is generally good, but don't go more than half of the old gen size.
-XX:ParallelCMSThreads=X
-XX:ParallelCMSThreads=X
设置 CMS 在执行可并行执行的操作时将使用的线程数.
set the number of threads that CMS will use when it is doing things that can be done in parallel.
-XX:+CMSParallelRemarkEnabled 备注默认是串行的,这样可以加快速度.
-XX:+CMSParallelRemarkEnabled remark is serial by default, this can speed you up.
-XX:+CMSIncrementalMode 允许应用程序通过在阶段之间暂停 GC 来运行更多
-XX:+CMSIncrementalMode allows application to run more by pasuing GC between phases
-XX:+CMSIncrementalPacing 允许 JVM 计算随时间变化的收集频率
-XX:+CMSIncrementalPacing allows JVM to figure change how often it collects over time
-XX:CMSIncrementalDutyCycleMin=X 最少花费在 GC 上的时间
-XX:CMSIncrementalDutyCycleMin=X Minimm amount of time spent doing GC
-XX:CMSIncrementalDutyCycle=X 以 % 的时间执行 GC 开始
-XX:CMSIncrementalDutyCycle=X Start by doing GC this % of the time
-XX:CMSIncrementalSafetyFactor=X
-XX:CMSIncrementalSafetyFactor=X
我发现,如果您将其设置为基本上始终在收集,您通常可以获得较短的暂停时间.由于大部分工作是并行完成的,因此您最终会遇到基本规律的可预测停顿.
I have found that you can get generally low pause times if you set it up so that it is basically always collecting. Since most of the work is done in parallel, you end up with basically regular predictable pauses.
-XX:CMSFullGCsBeforeCompaction=1
-XX:CMSFullGCsBeforeCompaction=1
这个很重要.它告诉 CMS 收集器在开始新的收集之前始终完成收集.如果没有这个,您可能会遇到这样的情况:它会丢掉一堆工作并重新开始.
This one is very important. It tells the CMS collector to always complete the collection before it starts a new one. Without this, you can run into the situation where it throws a bunch of work away and starts again.
-XX:+CMSClassUnloadingEnabled
-XX:+CMSClassUnloadingEnabled
默认情况下,CMS 会让你的 PermGen 增长,直到它在几周后杀死你的应用程序.这停止了.如果你使用反射,或者滥用 String.intern,或者使用类加载器做坏事,或者其他一些事情,你的 PermGen 只会增长.
By default, CMS will let your PermGen grow till it kills your app a few weeks from now. This stops that. Your PermGen would only be growing though if you make use of Reflection, or are misusing String.intern, or doing something bad with a class loader, or a few other things.
Survivor ratio 和tenuring theshold 也可以使用,这取决于您是否拥有长寿命或短寿命的对象,以及您可以忍受的幸存者空间之间的对象复制量.如果你知道你所有的对象都会留下来,你可以配置零大小的幸存者空间,任何在年轻一代集合中幸存下来的东西都将立即被永久保存.
Survivor ratio and tenuring theshold can also be played with, depending on if you have long or short lived objects, and how much object copying between survivor spaces you can live with. If you know all your objects are going to stick around, you can configure zero sized survivor spaces, and anything that survives one young gen collection will be immediately tenured.
这篇关于如何减少java并发模式失败和过多gc的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!