4

我正在尝试调整 GC,使其在短期基准测试中不会启动。

为此,我尝试将年轻一代设置得尽可能大,并确保我产生的垃圾少于 Eden 大小。

我使用了以下参数:

java -Xmx1g -Xms1g -Xmn1g -XX:NewSize=1000m -XX:MaxNewSize=1g -XX:SurvivorRatio=10000 -verbose:gc Main

但是由于某种原因,当 VM 内存仅为 300M 时,我仍然会看到 [Full GC] 日志,是否有任何我缺少的 JVM 调整?

4

3 回答 3

2

您的幸存者比例非常重要,10 000 您告诉 JVM 幸存者空间是伊甸园大小的 10000 分之一。

从文档

如果幸存者空间太小,复制集合会直接溢出到终身代。如果幸存者空间太大,它们将是无用的空。在每次垃圾回收时,虚拟机都会选择一个阈值次数,一个对象在其被永久保存之前可以被复制。选择此阈值以使幸存者保持半满。命令行选项 -XX:+PrintTenuringDistribution 可用于显示该阈值和新生代对象的年龄。它对于观察应用程序的生命周期分布也很有用。

很明显,由于幸存者空间比率如此之低,您的对象直接存储在终身代中。

当终身代满时,发生了一个主要的收集,这就是你[Full GC...]在日志中看到的原因。

如果你想让年轻一代更大的用途:

-XX:NewRatio=1

这意味着伊甸园和幸存者空间的组合大小将是总堆大小的一半。(我猜你不可能有更大的年轻一代)

-XX:NewSize如果你已经设置了-Xmn,你也不必设置,-Xmn从 1.4 开始也是一样的。而且我猜你不想从上面绑定年轻一代-XX:MaxNewSize,默认值是无限的。但是将年轻代的大小设置为与最大堆大小相同的值意味着您不会为老年代留出空间,所以我猜JVM会调整代的大小。

总而言之,在某些情况下,分配可以直接发生在终身代中。(对象会直接分配到老年代吗?

  • 如果年轻代分配失败,并且对象是一个不包含任何对象引用的大数组,则可以直接将其分配到年老代。在某些特定情况下,此策略旨在通过从老年代分配来避免收集年轻代。阈值大小为 64k 字。
于 2012-05-16T10:43:58.713 回答
2

你可以获得full GC,因为你的tenured空间已经被填满了(大对象被直接放入tenured空间)

我通常会尝试 4 - 24 GB 的 eden 大小,但要确保永久空间的大小为 0.5 到 2 GB。

于 2012-05-17T07:22:39.353 回答
1

如果您要释放大量对象,GC 仍然会运行,这不仅仅是等到您使用完所有分配的空间的问题,如果这样做的话,它会在运行时导致严重的 GC 抖动.

您应该查看您对对象处理的使用以及是否可以提高效率。查看 LMAX 破坏者模式,了解如何通过更新对象值而不是解除分配替换对象本身来重用对象。

话虽如此,这是一篇关于调整 GC 的非常好的文章 - http://developer.amd.com/documentation/articles/pages/4EasyWaystodoJavaGarbageCollectionTuning.aspx

于 2012-05-16T07:11:40.780 回答