什么是最佳空闲堆与总堆的比率?在这个比率的什么值下,我应该考虑增加堆大小/减小堆大小?
3 回答
理想的瞬时比率是 1。理想情况下,您的 JVM 将完全消耗它所需的内存,不多也不少。这是一个很难达到的目标;)
问题(正如 TNilsson 指出的那样)是您的应用程序的内存需求随着时间的推移而变化,因此您希望它有足够的空间不会导致持续收集/压缩的频率超出您的容忍范围,并且您希望它消耗足够小的空间,您不必购买更多的 RAM。
没有一个简单的答案,让我举两个例子:
示例 1 - 您的程序在启动时分配了 100M 的内存,然后在其余的运行中不分配任何内存。
在这种情况下,您显然希望堆大小为 100M(嗯,也许是 101 或其他东西,但您明白了……)以避免浪费空间。
示例 2 - 您的程序每秒分配 10M 的内存。没有任何数据的保留时间超过 1 秒。(例如,您正在进行需要大量临时数据的计算,完成后将返回一个整数......)
知道确切的数字可能不太现实,但这是一个例子。
由于您有 10M 的“实时”数据,因此您必须至少有 10M 堆。除此之外,您需要检查垃圾收集器的工作方式。简而言之,一次 GC 完成所需的时间是 O(live set),即“死”数据量并没有真正进入其中。使用恒定的活动集大小,无论您的堆大小如何,您的 GC 时间都是恒定的。这会导致更大的堆 -> 更好的吞吐量。
(现在,要真正把事情搞砸,你添加诸如压缩堆之类的东西,图像变得更加不清晰......)
结论 这是问题的简化版本,但简短的回答是 - 视情况而定。
这可能取决于您分配新对象的速率。垃圾收集涉及大量来自活动对象的跟踪引用。我刚刚处理了一种情况,即有大量可用内存(例如使用了 500 MB,500 MB 可用),但是发生了如此多的数组分配,以至于 JVM 将花费 95% 的时间进行 GC。所以不要忘记运行时内存行为。
所有这些性能调优文章都说“Java 中的对象分配非常快”,而没有提到某些分配会导致 1 秒的 GC 时间,这让我发笑。