java - 调整 GC 以进行大型缓存刷新

标签 java caching garbage-collection jvm heap-memory

我的内存中有一个很大的缓存(使用com.google.common.cache.LoadingCache实现)。 10 分钟后,使用 Scheduler 刷新,如下所示:

ScheduledExecutorService refresher = Executors.newSingleThreadScheduledExecutor();
    refresher.scheduleWithFixedDelay(
            new Runnable() {
                public void run() {
                    for (String key : cache.asMap().keySet()) {
                        cache.refresh(key);
                    }
                }
            }, 0, 10, TimeUnit.MINUTES);

我面临的问题是 - 每 10 分钟后老一代空间就会出现一个巨大的峰值。我假设发生这种情况是因为正在进行刷新,并且旧对象没有像创建新对象那样快地被清除。这可以在下图中看到。 (注:此图显示了 CMS GC,但我使用 G1GC 得到了相同的结果)。

enter image description here

我可以采取哪些步骤来优化这个特定问题?我可以使用 CMS 或 G1GC,但这些尖峰必须被压平。原因是,Full GC 正在启动,应用程序将进入 Stop The World GC

我可以做些什么来优化缓存代码以更有效地刷新它,这样就不会出现突然的峰值?

最佳答案

I am hypothesizing that this is happening because of the refresh taking place and old objects are not being cleared as quickly as new ones are created.

使用分配分析器可以帮助测试该假设。

What are the steps I can take to optimize this specific issue? I can use CMS or G1GC, but these spikes have to be flattened. The reason is, Full GC is getting kicked in and the app is going into Stop The World GC.

Full GC 通常表明收集器的并发部分跟不上分配速率。但要验证,您应该检查 GC 日志以了解 Full GC 的原因。 您可以尝试降低 IHOP、为并发 GC 工作提供额外的 CPU 核心或调整刷新任务的节奏,以便它们在 10 分钟间隔内更加分散。

您还应该检查混合集合的 GC 启发式日志(假设 G1GC)是否能够为混合集合选择任何区域。如果它直接从年轻回收到完整 GC,而没有任何混合回收,那么由于缓存的分配模式,其他一些启发式方法可能会出现问题。

关于java - 调整 GC 以进行大型缓存刷新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71603019/

相关文章:

java - 在 Java swing GUI 中将 ActionListener 类添加到多个 JButtons?

c# - 使用 Application_BeginRequest + 重定向进行 HTML 版本控制中的 Javascript、CSS

heroku - 如何为 NestJS 缓存管理器传递 REDIS_URI?

go - 垃圾收集器和延迟函数之间的冲突?

c# - String 和 Char 类型如何存储在 .NET 的内存中?

java - 如何从我的代码中删除 protected void Finalize() 方法

java - 如何在 Android Studio 中显示参数类型标签?

Java如何删除设置了IMMUTABLE位的文件

java - 当要模拟的方法有多个参数时,如何使用 Jmock 编写自定义约束

c# - 使用 ImmutableSortedSet<T> 进行线程安全缓存