我正在开发一个应用程序,其目的是尽可能快地计算报告。
我的应用程序使用大量内存;超过100 Go。
自上次发布以来,我发现性能大幅放缓。我的调查显示,在计算过程中,我在40到60秒之间收集了很多垃圾! (JMC告诉我他们 SerialOld 但我不知道它究竟意味着什么)当然,当JVM是垃圾收集时,应用程序绝对是冻结的
我现在正在调查这些垃圾收集的来源......这是一项非常艰苦的工作。
我怀疑,如果这些垃圾收集很长,那是因为他们在finalize
函数中花费了很多次(我知道,在我们从其他团队整合的所有库中,有些他们使用终结者)
但是,我不知道如何确定(或不)这个假设;如何找到哪个终结器很耗时。
我正在寻找一个好的工具甚至是一个好的方法
正如你所看到的,当我有一个时,我总是有很多“待定终结者” 记录旧垃圾
令人惊讶的是,当我使用JVisualVM时,上图 从右到左定期滚动。当旧垃圾是 触发,滚动停止(直到这里,它看起来正常,这是 最终的世界)。但是,当滚动突然重启时,确实如此 不是从旧垃圾的末尾,而是从Pending Serializer的末尾
这让我觉得终结器阻止了JVM
有没有人对此有解释?
非常感谢你 菲利普
答案 0 :(得分:2)
我的应用程序使用大量内存;超过100 Go。
JMC告诉我他们是SerialOld,但我不知道它究竟意味着什么
如果您使用100GB堆的串行收集器,那么可以预期长时间暂停,因为串行收集器是单线程的,并且一个核心只能在每个单位时间内节省大量内存。
只需选择任何一个多线程收集器就可以产生更短的暂停时间。
但是,我不知道如何确定(或不)这个假设;如何找到哪个终结器很耗时。
通常:收集更多数据。对于GC相关的事情,您需要启用GC日志记录,在Java代码中花费的时间(无论是您的应用程序还是第三方库),您需要一个分析器。
答案 1 :(得分:1)
以下是我要调查终结者理论的方法。
使用您喜欢的Java分析器启动JVM。
让它运行足够长的时间以获得完整的堆。
启动探查器。
触发垃圾回收。
停止分析器。
现在,您可以使用分析器信息来确定哪些(如果有)finalize
方法占用了大量时间。
但是,我怀疑真正的问题是内存泄漏,而且你的JVM正在到达堆满了无法恢复的对象的程度。这可以解释频繁的" SerialOld"垃圾收集。
或者,这可能只是一个大堆问题。 100Gb是......大。