为什么Java的CMS垃圾收集器不允许已使用的堆大小增长到可用堆大小?

huangapple go评论76阅读模式
英文:

Why doesn't the Java CMS Garbage Collector allow the used heap size to grow to the available heap size?

问题

我正在测试G1GC和CMS垃圾收集器之间的差异。运行相同的程序会产生不同的堆大小使用情况(可能是预期的)。

下面的图片显示了G1GC(左侧)与CMS GC(右侧)的比较情况。G1GC设法运行整个程序,而在使用CMS时,会引发“outOfMemoryException”。

因此,我的问题是:为什么CMS不允许已使用的堆大小达到可用的堆大小?堆大小在达到8.00GB时停止增长,而可用的堆大小为10GB。

英文:

I am testing the differences between G1GC and the CMS Garbage collectors. Running the same program yields different heap size usages (maybe as expected).

The below image shows the G1GC (left) compared to the CMS GC (right). G1GC manages to run the whole program whereas the when using the CMS, an outOfMemoryException is raised.

为什么Java的CMS垃圾收集器不允许已使用的堆大小增长到可用堆大小?

Hence, my question: Why doesn't the CMS allow the used heap size to reach the available heap size? The heap size stops growing at 8.00GB with an out of memory exception when 10GB is available.

答案1

得分: 2

简短的回答是,当堆内存填满时,CMS在管理内存方面不如G1GC好。这是CMS逐步淘汰的原因之一。

稍长一点的回答是,CMS中未使用的2GB空间保留用于在Eden空间进行小型(复制)GC时疏散对象。相比之下,G1GC似乎能够在老年代空间填满时调整(缩减)Eden空间。

请注意,这实际上可能是不切实际基准测试的结果。在典型应用程序中,小型垃圾回收将成功删除大多数新对象。在您的基准测试中,几乎所有内容都保持可访问,因此分配的大多数对象最终进入老年代空间。

你可以采取什么措施呢?

  1. 切换到G1GC。在大多数情况下,它比CMS更好。(最终您将别无选择。CMS在Java 9中已被弃用,并在Java 14中被移除。)

  2. 您可以减小Eden空间的大小:具体调整NewSize和MaxNewSize。然而,这对正常工作负载来说有不利之处。它可能会导致年轻对象过早进入老年代,从而增加CMS收集器的负担。

  3. 有一些更新的收集器专为“满”堆设计,可以考虑使用。

英文:

The short answer is that CMS is not as good as managing memory when the heap fills up as G1GC is. This is one of the reasons that CMS is being phased out.

A slightly longer answer is that the 2GB of unused space in CMS is reserved for evacuating objects in minor (copying) GCs of the Eden space. By contrast, G1GC seems to be able to adjust (shrink) the Eden space as the Tenured space fills up.

Note that this could actually be an artifact of an unrealistic benchmark. In a typical application, the minor collections will succeed in deleting most of the new objects. In your benchmark, it looks like nearly everything is remaining reachable, so most of the objects allocated end up in the Tenured space.

What can you do about it?

  1. Switch to G1GC. In most cases it is better that CMS. (Eventually you won't have a choice. CMS was deprecated in Java 9, and has been removed in Java 14.)

  2. You can change reduce the size of the Eden space: specifically adjust the NewSize and MaxNewSize. However, this has disadvantages for a normal workload. It is liable to lead to young objects being tenured too soon which will increase the load on the CMS collector.

  3. There are newer collectors that are designed to work better with "full" heaps.

huangapple
  • 本文由 发表于 2020年10月5日 16:47:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/64205297.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定