我的Java应用程序维护一个内部缓存,可以增长到10演出。到期策略设置为30分钟或达到内存阈值时(我正在使用本地ehcache)。很明显,在30分钟之后,所有缓存的对象都将在旧版本中,并且需要一个完整的gc来收集它们。至于现在停止世界暂停可能达到6秒,我想减少它。
平均对象大小为500k,但最高可达1mcg,因此我们讨论的是10000-20000个缓存对象(实际上是字节数组)。
GC优化的最佳策略是什么?我知道我可以脱离堆,但它是最后的解决方案。
谢谢!
答案 0 :(得分:4)
10GB缓存不是你应该在堆中做的事情。使用ByteBuffers进行缓存。对象创建不应该那么昂贵。这样就不会涉及GC,您可以自己管理所有内容。
例如,如果在Java数据库管理系统中实现页面缓存,则不会为其创建对象,而是使用字节缓冲区或托管字节缓冲区或最佳直接字节缓冲区。您可以详细了解这三个here。
如果你处理的更多,那么让我们一次说出一百万个对象就会看到GC的时间份额在上升。我看到我们管理大量节点进行数据处理的情况,而且非常慢。然后,我们切换到直接字节缓冲区方案,甚至使用了一些额外的技术,我们能够容纳更多的数据(对象至少每个成本为24字节)并且不再考虑对象。最后我们处理数据而不是对象。这使性能提高了很多倍,我们能够处理比预期更多的数据。
之后我们注意到这一切都适合数据库,这就是我们抓住一切的重点。
请查看直接缓冲区可以为您做什么。
答案 1 :(得分:2)
我经常使用缓存服务,在JVM堆中保存10-30 GiB的数据。 Concurent Mark Sweep(GC)算法可以很好地处理这些情况,使最大停止世界暂停约100ms(但绝对数量取决于硬件)。
您可以在我的博客中找到用于缓存应用程序和堆大小调整的GC调优check list。
Here您可以找到有关Concurent Mark Sweep算法本身的更多信息。