7

通过 GC 调整,我成功地获得了实时 Java 应用程序的性能并避免了可识别的 GC 暂停。但是,这最多可容纳约 20 GB 的堆空间。

硬件成本的降低使得即使是 100GB 的 RAM 机器也可以负担得起。但是,由于 GC 暂停,Java 仍然存在,更高的堆大小(如 50 GB)可能会让您经常陷入噩梦。

我知道有诸如堆外和分布式堆之类的选项。但是,off-heap 具有 se/derialization 的缺点,并且手头上的分布式堆增加了维护成本。此外,在分布式堆中,您实际上并没有充分利用 RAM(比如 64 GB),这些天作为商品变得普遍。

那么,要充分发挥 RAM 的潜力,Java 应用垂直扩展有哪些好的解决方案呢?

4

3 回答 3

5

我正在研究一个名为Banana的原始收藏库。Banana 解决了这些确切的问题。它很快就支持 LinkedLists、HashMaps 和可能的其他数据结构,而无需保留 N 个对象的开销。基本上 - 整个存储可以在一个 int[] 数组(或许多)内。

虽然我还没有正式发布它,但其中大部分都经过了很好的测试,我已经在 144GB RAM 的服务器上成功运行了它,保持了快速和一致的性能,没有任何 GC 暂停。

查看这个哈希图基准,了解如何使用 Banana 存储数据以及它的垂直扩展能力如何。

https://github.com/omry/banana/wiki/Long-to-fixed-size-object-benchmark

有关更多信息,请参阅wiki

于 2013-07-17T06:07:46.603 回答
0

垃圾收集时间是堆中活动对象数量的函数。这意味着,如果您的分配率非常高,但活动对象的数量总是很低,您可以使用尽可能多的 RAM,而不会出现明显的停顿。

这句话对于 Troughput Collector ( -XX:+UseParallelOldGC) 尤其正确。

如果您使用 CMS,那么您可能需要检查其增量模式 ( -XX:+CMSIncrementalMode)。它将触发更小的 CMS 周期来清理你的堆的一小部分,同时利用你的硬件并且没有 STW 暂停。

如果 CMS 不是一个选项,那么您应该看看 G1 ( -XX:+UseG1GC),它是为大型堆设计的新垃圾收集器。原则是:在每个循环中只清理堆的几个区域,但要确保这些区域包含很多死对象(快速收益)。

希望有帮助!

资料来源:

于 2013-07-17T11:52:47.190 回答
0

我做了一些关于缩放 JVM 堆大小的研究。您可以在此处此处阅读更多详细信息。

主要结论:young GC pause 有常量和变量两个部分。

常量组件取决于旧空间大小,对于 64GiB,我希望它为 80ms-120ms(取决于硬件)。

变量组件依赖于年轻空间中对象的生存(因此它从一个集合变为另一个集合)。它确实是特定于应用程序的,但您通常可以通过减少年轻空间来减少它(以更频繁的暂停为代价)。

对于 4 GiB 的年轻空间,您有 500 毫秒。假设变量组件是 400 毫秒,如果你将年轻空间减少到 1 GiB,你应该有大约 200 毫秒的暂停(但每秒 2 次)。

另一种方法是使用更多的 CPU 内核,年轻 GC 并行非常好

于 2013-07-19T16:43:17.677 回答