gpt4 book ai didi

java - 对象不断提升到 Old Gen

转载 作者:行者123 更新时间:2023-11-30 10:43:10 27 4
gpt4 key购买 nike

我正在使用一个提供 REST API 的应用程序。它仅适用于 GET 请求,通常最多花费 100 毫秒来处理最繁重的请求。

最近我们开始面临一个问题,即堆有时会被填满,而完整的 GC 会花费大量时间,这确实影响了我们的客户。

  • 堆大小 - 5GB
  • 每秒并发请求 - 最多 50
  • 每个请求最多消耗1-2MB(很少有请求消耗12MB的堆)
  • 应用程序对老一代和年轻一代都使用并行 GC。
  • JDK 1.7

从我的角度来看,这个应用程序应该在工作的一开始就提升 Old Gen 中的一些对象,然后所有新对象都应该从 Eden 或 Survivor 空间中移除。因此 full GC 永远不会到来。然而,有些对象不断被提升到 Old Gen,这让我很困惑。

一些额外的发现:

  • 我们启用了 JVM 标志 -XX:+PrintTenuringDistribution 并根据此标志输出,即使在没有显着负载的情况下,应用程序启动后几分钟内新的 tenuring 阈值就等于 1。
  • 当应用程序消耗了几乎所有允许的内存时,我们进行了一次内存转储,根据 MA​​T 分析器统计,几乎所有转储对象都无法访问(所以,我不明白为什么它们会被提升到 Old Gen)<
  • 几乎不使用幸存者空间。看起来新对象直接从 Eden 空间提升到 Old gen。
  • 次要 GC 每 10-20 秒出现一次。
  • 增加 Eden/Survivor 空间并没有帮助解决问题(tenuring threshold 仍然是 1)

那么,能否请您指教:

  • 为什么任期阈值会这么快变成 1?[已解决]
  • 我可以采取哪些额外步骤来避免将新对象提升到旧代?

如果您需要一些额外的信息,请告诉我。

编辑:

JVM 参数(更新):

-XX:MaxPermSize=512m -Xmx7g -Xmn4g -verbose:gc -Xloggc:gc.log -XX:+PrintGCDetails -XX:+PrintTenuringDistribution

应用程序日志:

Desired survivor size 520617984 bytes, new threshold 15 (max 15)
[PSYoungGen: 3235245K->231763K(3665920K)] 3942774K->939308K(4760064K), 0.0905430 secs] [Times: user=0.31 sys=0.00, real=0.09 secs]
603.561: [GC
Desired survivor size 521142272 bytes, new threshold 15 (max 15)
[PSYoungGen: 3369299K->330881K(3684864K)] 4076844K->1038442K(4779008K), 0.1343473 secs] [Times: user=0.51 sys=0.00, real=0.13 secs]
606.347: [GC
Desired survivor size 506462208 bytes, new threshold 15 (max 15)
[PSYoungGen: 3507329K->215655K(3685376K)] 4214890K->923233K(4779520K), 0.0925060 secs] [Times: user=0.36 sys=0.00, real=0.09 secs]
609.084: [GC
Desired survivor size 492306432 bytes, new threshold 15 (max 15)
[PSYoungGen: 3392103K->213344K(3713536K)] 4099681K->920945K(4807680K), 0.0802729 secs] [Times: user=0.30 sys=0.00, real=0.08 secs]

重要细节:

即使当我只使用 1 个线程(每个请求消耗约 10 MB)开始性能测试时,老一代也在不断增长: Old Gen with 1 thread perf test

如果我启动 GC,它会成功清理内存

如果我进行堆转储,Mat Analyzer(或 Yourkit)再次显示 80% 的对象无法访问

最佳答案

如果您的任期阈值迅速下降到 1,这听起来像是您正在使用的其他一些参数导致了这种情况。除了日志记录选项和最大堆之外,我会尝试删除所有其他调整参数,并且只在您确定它们确实有帮助时才添加每个参数。你设置的越多,你就越有可能得到一些奇怪的行为。您可以尝试强制使用终身制阈值,但我怀疑这充其量只会隐藏您的问题。

Desired survivor size 341835776 bytes, new threshold 1 (max 15)

为了尝试增加幸存者大小以避免完整幸存者触发完整 GC,幸存者大小或仅一代正在使用整个年轻空间。

我会尝试让年轻一代变得更大。你需要一个至少有幸存者空间的伊甸园,这样你的 child 应该至少有 1 GB,最好是大几倍。我会尝试 4 GB 年轻或 2 Gb,具体取决于您有多少空间。例如

-Xmn2g -Xmx5g

-Xmn4g -Xmx7g

如果你有足够的内存,例如64 GB 或更多,我会尝试更大的空间,例如

 -Xmn24g -Xmx32g

如果看起来没有帮助,则减少年轻的空间。

关于java - 对象不断提升到 Old Gen,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37870067/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com