如何优化Java堆中未使用的空间

问题描述:

请不要对此表态。我只是重复我从不同渠道拼凑出来的东西。 HotSpot JVM使用线程本地分配缓冲区(TLAB)。 TLAB可以同步或不同步。大多数情况下,TLAB不同步,因此线程可以非常快地分配。有大量的这些TLAB,以便活动线程获得他们自己的TLAB。活动较少的线程共享一个同步的TLAB。当线程耗尽其TLAB时,它会从池中获取另一个TLAB。当池用完TLAB时,则触发或需要Young GC。如何优化Java堆中未使用的空间

当池中的TLABs用完时,仍然会有剩余空间的TLAB。这个“未使用的空间”加起来很重要。人们可以看到这个空间,因为在保留的堆大小或最大堆大小达到之前触发GC。因此,堆有效地缩小了10-30%。至少这是我从查看堆使用情况图的猜测。

如何调整JVM以减少未使用的空间?

您也可以自行调整使用命令行选项设置-XX:TLABSize

然而与大多数的这些“深跌和肮脏”的设置,你应该改变这些的时候要非常小心,并密切监测更改的影响。

你是对的,一旦没有TLABs,将会有一个年轻一代的收集,他们将被清理。

我不能告诉太多,但有ResizeTLAB允许JVM能够根据分配统计我猜,伊甸园大小等调整它还有一个叫做TLABWasteTargetPercent标志(默认情况下它是1%)。当前的TLAB不能再容纳一个对象时,JVM必须决定如何操作:直接分配给堆,或者分配一个新的TLAB。

如果该物件尺寸大于1% of the current TLAB size则直接分配;否则当前的TLAB已经退役。

所以我们说的TLAB的电流大小(TLABSize,默认情况下它是零,这意味着它会自适应)是100 bytes(所有的数字都是理论上的),那1%是1 byte - 这是TLABWasteTargetPercent。目前你的TLAB被填充了98个字节,你想要分配的对象是3个字节。它不适合这个TLAB,同时它大于1个字节的阈值=>它直接在堆上分配。

另一种方法是,你的TLAB是满99.7字节,你试图分配一个半字节的对象 - 它不适合;但小于1个字节;因此这个TLAB承诺并且给你一个新的。

据我所知,还有一个参数叫做TLABWasteIncrement - 当你不能在TLAB中分配(并直接在堆中分配)时 - 这样这个故事不会永远发生,TLABWasteTargetPercent增加了这个价值(默认为4%)增加了退休此TLAB的机会。

还有TLABAllocationWeightTLABRefillWasteFraction - 稍后可能会更新这篇文章