简体   繁体   English

JVM 和 GC 调整 - 没有 Full GC 的理论

[英]JVM and GC tuning - theory for no Full GC

I have large scale application with two type of objects: long living (cache) and short living (request-process-response).我有两种类型的对象的大规模应用程序:长寿命(缓存)和短寿命(请求-过程-响应)。 Theoretically, with this type of application, I think it is possible to configure Young vs Old spaces, so Old space consumption is constant, resulting in no Full GC.理论上,用这种类型的应用,我觉得可以配置 Young vs Old 空间,所以 Old 空间消耗是恒定的,导致没有 Full GC。

I've changed newSize-maxNewSize params, but, Old heap continues to rise until Full GC.我已经更改了 newSize-maxNewSize 参数,但是,旧堆继续上升,直到 Full GC。 After each Full GC, consumption is down to 20% (cache takes 20%).每次 Full GC 后,消耗下降到 20%(缓存占 20%)。 For some reason, my objects gets into Old space.出于某种原因,我的对象进入了旧空间。 I have two suspects why are moved to Old space:我有两个怀疑为什么要搬到旧空间:

  • Per this article: http://chaoticjava.com/posts/gc-tips-and-memory-leaks/ it's told if you have big objects allocated, those go directly to Old space.根据这篇文章: http://chaoticjava.com/posts/gc-tips-and-memory-leaks/如果您分配了大对象,那些 go 直接分配给旧空间。 Is this true, and if it is, is there JVM Option param that can set object size threshold for Young space?这是真的吗,如果是,是否有 JVM 选项参数可以设置年轻空间的 object 大小阈值?

  • If I understood the process correctly, objects are switched between To-From survival sections before are moved to Old section.如果我正确理解了该过程,则对象会在 To-From 生存部分之间切换,然后再移至旧部分。 Is there param that can set how many switches between To and From is to be done before moving to Old space?是否有参数可以设置在移动到旧空间之前要在 To 和 From 之间进行多少次切换?

Any other tips?还有其他提示吗?

Thanks, Amar谢谢,阿马尔

It does sound like your survivor spaces are not big enough.听起来您的幸存者空间确实不够大。 You need to make them large enough that no objects need to be collected.您需要使它们足够大,以至于不需要收集任何对象。 An object is only switched into and out of survivor space once. object 只进出幸存者空间一次。

If you are allocating large objects, can you use an Object pool for them avoiding the need to GC them.如果您正在分配大对象,您可以使用 Object 池来避免对它们进行 GC。 Have you considered using an object pool for your request/process/response data as well?您是否考虑过将 object 池也用于您的请求/处理/响应数据? eg a simple one is to use a ThreadLocal.例如,一个简单的方法是使用 ThreadLocal。

Have you tried the G1 collector which is designed to progressively collect all your memory and reduce the big hit of a full GC.您是否尝试过 G1 收集器,该收集器旨在逐步收集您的所有 memory 并减少完整 GC 的大命中。

Are you sure that the growth of the old generation is just not cached objects?你确定老年代的增长只是没有缓存对象吗? Unless your cache is fixed and never changing, you're going to be continually adding to it.除非您的缓存是固定的并且永远不会更改,否则您将不断地添加它。 As objects that have made it to the old generation expire from that cache they're going to stay in memory until the next full GC.由于已经进入老年代的对象从该缓存中过期,它们将留在 memory 直到下一次完整的 GC。

I've had much better luck with the concurrent mark sweep collector to entirely eliminate long pauses from full GCs.并发标记扫描收集器完全消除了完整 GC 的长时间停顿,我的运气要好得多。 It takes a bit of tuning and it can vary per application.这需要一些调整,并且可能因应用程序而异。 Here's what we use to run a 24GB 64-bit JVM with sub-second GC pauses while serving 100+ page requests per second with large caches:以下是我们用来运行 24GB 64 位 JVM 的方法,其 GC 暂停时间为亚秒级,同时通过大型缓存每秒处理 100 多个页面请求:

-Xms24g -Xmx24g -XX:+UseCompressedOops -XX:NewRatio=4 -XX:SurvivorRatio=8    
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+DisableExplicitGC  
-XX:+UseCMSInitiatingOccupancyOnly -XX:+CMSClassUnloadingEnabled  
-XX:+CMSScavengeBeforeRemark -XX:CMSInitiatingOccupancyFraction=68

Is there param that can set how many switches between To and From is to be done before moving to Old space?是否有参数可以设置在移动到旧空间之前要在 To 和 From 之间进行多少次切换?

Yes, -XX:MaxTenuringThreshold是的, -XX:MaxTenuringThreshold

This switch determines how many times the objects hop between the "From" and "To" Survivor spaces before getting promoted to the older generation.此开关确定对象在提升到老一代之前在“From”和“To”Survivor 空间之间跳跃的次数。 The largest value is 15 for Java 6 and 31 for earlier JDKs. Java 6 的最大值为 15,早期 JDK 的最大值为 31。 The default value is 15 for the parallel collector and is 4 for CMS collectors . 并行收集器的默认值为 15,CMS 收集器的默认值为 4

From the Sun JVM GC docs,来自 Sun JVM GC 文档,

Use -XX:MaxTenuringThreshold=0 to move an object that survives a young generation collection immediately to the tenured generation.使用 -XX:MaxTenuringThreshold=0 将在年轻代收集中幸存的 object 立即移动到终身代。

As you want to do the opposite of that, if you haven't set this value it would be at the default, which is quite enough to decide whether the object does need to go into Old - provided as @Peter says, the survivors are large enough to hold those objects.正如你想做的相反,如果你没有设置这个值,它将是默认值,这足以决定 object 是否需要将 go 转换Old - 正如@Peter所说,幸存者是大到足以容纳这些物体。

Whats your SurvivorRatio set at?您的 SurvivorRatio 设置为多少? And what's your total Heap?你的总堆是多少?

Object life time characteristics play a critical role here.Important tuning knobs are size of survivor space, tenuring threshold and size of young generation. Object 生命周期特征在这里起着至关重要的作用。重要的调整旋钮是幸存者空间的大小、任期阈值和年轻代的大小。 Strategically we want objects to die young, so if there is enough gap between minor collections lot of object will die in young generation.从战略上讲,我们希望对象在年轻一代中死亡,因此如果次要 collections 之间有足够的差距,很多 object 将在年轻一代中死亡。 Besides we can configure the tenuring threshold so that the objects remain in survivor space for desired number of collections.此外,我们可以配置任期阈值,以便对象在幸存者空间中保留所需数量的 collections。

As we keep large number of live objects in the survivor space and keep copying them from one space to other for a number of minor GC it increases the cost of minor GC.由于我们在幸存者空间中保留了大量活动对象,并不断将它们从一个空间复制到另一个空间以进行多次次要 GC,因此增加了次要 GC 的成本。

Keeping a large young generation naturally increases the gap between consecutive minor collections and gives more time to objects to die.保持较大的年轻代自然会增加连续次要 collections 之间的差距,并为对象提供更多死亡时间。

One can strike a right balance by experimenting with these variables to reduce the object promotions to old generation with a view on acceptable young generation pauses可以通过试验这些变量来达到适当的平衡,以减少 object 对老一代的提升,并考虑可接受的年轻一代暂停

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM