java - Major GC 性能下降
问题描述
我们的应用程序经常中断,基本上堆会随着时间的推移而增长,以至于 GC 需要大量的 CPU 时间并执行几分钟,从而大大降低了应用程序的性能。该应用程序位于带有 tomcat 服务器的 JSF 中。
与此同时,我们:
- 将堆大小从 15G 增加到 26G (-Xms27917287424 -Xmx27917287424)
- 进行几个堆转储(我们正在尝试使用这些来确定问题)
- 激活的 GC 日志
随着堆大小的增加,GC 不会执行很长时间,但仍会占用大量 CPU 并冻结应用程序。
所以问题是:
- 这是正常的吗?当 GC 执行时它会释放内存,所以我认为这可能不是内存泄漏(对吗?)
- 有没有优化 GC 的方法,或者这种行为只是应用程序本身出现问题的症状?
- 如何在不进行堆转储的情况下对其进行监控和分析?
更新: 我将 JSF 从 2.2 更改为 2.3,因为一些堆转储指出 JSF 正在使用大量内存。那没有成功,昨天我们又停电了,但这一次有点不同(从我的角度来看)。同样这一次,我们不得不重置tomcat,因为应用程序在一段时间后不再工作了
在这种情况下,垃圾收集器在de old gen heap未满时运行,而新生代GC一直在运行。¿ 这可能是什么原因?
解决方案
正如评论中所说,应用程序的行为看起来并不合理。您的代码不断分配导致堆空间填满的对象,从而导致 GC 运行。似乎没有内存泄漏,因为 GC 回收了大量空间并且总体使用空间并未持续增加。
一个问题似乎是大量对象在被收集之前被提升为老一代。由于对象的重定位和重新映射(假设您使用的是压缩算法),主要 GC 周期在 CPU 方面的成本更高。
为了减少这种情况,您可以尝试增加年轻代的大小。当您增加整体堆大小但还不够时,就会发生这种情况。理想情况下,您希望在次要 GC 周期中收集大部分对象,因为这实际上是免费的(在收集 Eden 空间中的对象时,GC 不会对它们做任何事情)。您可以使用-XX:NewRatio=
or-XX:NewSize=
标志来执行此操作。您还可以尝试更改幸存者空间大小,再次增加在使用前收集的对象数量。-XX:SurvivorRatio=
(为此使用标志)。
对于监控,我发现 Flight Recorder 和 Mission Control 非常有用,因为您可以深入了解分配了多少特定类型的对象的详细信息。连接到正在运行的 JVM 或进行转储以供以后分析也很容易。
推荐阅读
- javascript - 如何删除整行取决于关键字?
- r - 构建用于股票预测的 LSTM
- angular - 错误 TS2503:找不到命名空间“google”。Angular-7
- android - Android XML 动态设置边距高度
- reactjs - 有没有办法在获取方面控制 create-react-app 中的 Service Worker - 它在初始加载后缓存 2000 个 HTTP 请求
- github - 有没有办法通过 GitHub 操作推送更改?
- javascript - 如何提交
- javascript - 我如何在没有自己的服务器的情况下使用 webrtc?
- django - 如何在 django 的布局模板中添加动态模板?
- javascript - 使用jQuery单击锚标记时div内容不隐藏