为什么JVM仅在使用CMS垃圾收集器时会随着时间的推移而减慢?

时间:2017-08-26 02:50:37

标签: java performance garbage-collection jvm nashorn

我有一个使用Nashorn的应用程序。出于我的示例的目的,我创建了一个ScriptContext,我通过执行一些Javascript来创建一些全局变量,然后通过在紧密循环中调用NashornScriptEngine#eval(String, ScriptContext)在一个线程中反复使用该上下文。我没有将结果存储在任何地方,据我所知,我的应用程序代码不会导致任何副作用。

使用默认的GC,这可以无限期地正常工作。但是,当我使用-XX:+UseConcMarkSweepGC运行相同的应用程序时,性能会随着时间的推移而显着降低。程序启动时,运行1,000,000次迭代大约需要2分钟。但是2小时后,相同的1,000,000次迭代大约需要4分钟。它从那里开始变得更糟。

我还经常测试丢弃NashornScriptEngine实例和ScriptContext,完全从头开始。此时,我的应用程序没有引用上一次执行中的任何变量。这并没有改善这些性能问题。

知道发生了什么事吗?我需要使用-XX:+UseConcMarkSweepGC运行,因为这只是一个较大的长期应用程序的一小部分。

我在下面的Java Mission Control中有一些截图(摘自Flight Recorder)。

谢谢!

Heap Reference Objects Top Growers

在这里,我选择了两个GC,一个从录制开始,一个从最后开始。请注意“JNI弱参考”时间如何显着增加,“GC暂停”也是如此。

GC At Beginning GC At End

2 个答案:

答案 0 :(得分:3)

有一个错误https://bugs.openjdk.java.net/browse/JDK-8177098。 你能尝试一下解决方法 - 每次都重新创建NashornScriptEngineFactory吗?

答案 1 :(得分:0)

正如您自己所说,它在JNI ref处理中花费了大量时间。默认情况下,这是单线程的。设置-XX:+ParallelRefProcEnabled以使其并行运行。

由于您正在使用动态生成字节码的nashorn引擎,因此也可能是类卸载或缺少类的问题,但这在您的日志中并不明显。