【问题标题】:JVM garbage collection suddenly takes a lot of CPUJVM 垃圾回收突然占用大量 CPU
【发布时间】:2018-06-11 14:43:25
【问题描述】:

我有一个从服务器读取 XML 响应的应用程序。 这很好用,直到我尝试阅读 ~200.000 个 XML 响应。当我达到那个神奇的数字时,处理时间会减少 10 倍。 当我让它运行时,JVM 有时会说 GC 占用了 90% 的 CPU 时间。所以我首先尝试优化我的代码——使用字段而不是局部变量,在我的字符串上使用实习生(因为我有很多副本)等等。

这有点帮助,但是在大约 100k 个 XML 文件之后它仍然很慢。然后我尝试使用 Visual VM 来查看发生了什么,我看到的是:

直到 18:02,一切正常。然后突然间垃圾收集器开始发疯,并窃取 CPU 时间,这反过来又稳定了内存消耗。如果我们达到堆的最大内存,我会理解这一点,但我已将最大堆大小设置为 8 GB。

此时并没有什么不同,它基本上是一个巨大的循环,一遍又一遍地做同样的事情。

发生了什么,在这种情况下我该怎么办?

【问题讨论】:

  • 这个问题太笼统和模糊了。你制造了太多垃圾,你需要制造更少的垃圾。
  • 我建议在 JFR 开启 -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:FlightRecorderOptions=defaultrecording=true,dumponexit=t‌rue,dumponexitpath=p‌​ath 或类似的情况下运行。分析录音以查看内存中的内容。
  • 我猜?您将这些 XML 响应保存在内存中的某个地方。
  • 创建垃圾不一定是问题。 Azul 展示了他们的 JVM 处理在 700 cres 上运行的 700 个线程,在 500 GiByte 堆上创建 20 GiByte/s 的垃圾,甚至不费吹灰之力,这就是 10 年前的 VM 和 GC 技术。问题是垃圾。
  • 正如@JörgWMittag 所说,垃圾不是问题 - 随心所欲地创建。但要确保它变成垃圾。查看 JFR 的输出并确定存在什么问题。可能就像在某事上调用 close() 一样简单。

标签: java memory-management garbage-collection jvm heap-memory


【解决方案1】:

您的堆大小不足以满足您的工作流程。您可能有内存泄漏,或者只是特定于您的应用程序。

并行 GC 算法的正常模式(您已启用)

Young GC
Young GC
... 
Full GC

不过,一旦旧空间已满(您的设置约为 5.6 GiB),模式将切换到

Full GC
Full GC
Full GC
...

Full GC 的时间要长一个数量级,因此应用程序几乎一直处于 GC 暂停状态(CPU 消耗高)。 VisialVM 错误地绘制了 GC CPU 使用率图表,实际上蓝色尖峰与 CPU 图表上的橙色线一样高。

如果由于内存泄漏导致内存使用量增加,您应该解决这个问题。

如果是特定于应用程序设计,则需要将旧空间增加

  • 增加总堆大小
  • 或减少年轻空间(-Xmn=SIZE 选项)为旧空间节省更多内存

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-16
    • 2016-06-18
    • 1970-01-01
    • 2019-02-08
    • 1970-01-01
    • 2016-10-14
    • 1970-01-01
    • 2011-02-23
    相关资源
    最近更新 更多