为什么Java 8启动速度较慢

4
在我们将Java 6(u39)迁移到Java 8(u51)的过程中,我们发现Java 8的热身时间比6更长。我们发现这个问题不仅出现在用Java程序运行的性能测试中,还出现在启动带有Java 8的Tomcat 7(u35)时的初始请求中。我们正在运行Linux Redhat 64位系统。对于性能测试程序,我们发现在10次迭代后,Java 6的稳态性能接近215毫秒,而Java 8则需要800毫秒,并且需要70多次迭代才能达到215毫秒。当我们以并发度10在tomcat webapp上运行JMeter测试(使用Spring 2.5、jackson、xerces XML解析器、jedis等)时,在重新启动Java 6之后,它只需要不到一分钟就可以提供稳态性能,而Java 8则需要大约5-6分钟,并且直到那时速度才会变得慢数个数量级。在Java 8中使用“-XX:-TieredCompilation” VM HotSpot选项关闭分层编译可以解决性能测试程序的热身问题,并且稳态性能没有变化,这很奇怪,因为分层编译实际上应该让热身更快。但是关闭分层编译并没有给Tomcat服务器的热身时间带来类似的改进。我欢迎任何建议来解决这个问题,因为在生产环境中部署新版本可能会变得很麻烦,因为热身时间太长了。谢谢,Suresh

听起来类似于“-server”和“-client”配置之间的区别。您可能希望在问题中为两种配置都添加“java.*”系统属性。 - Thorbjørn Ravn Andersen
(由您的应用程序报告 - 而不是您自己设置的) - Thorbjørn Ravn Andersen
这个问题可能会在Stack Exchange频道Server Fault和/或Super User上得到更好的回应,因为它听起来更像是一个服务器软件和配置问题,而不是一个编程挑战。 - Bobulous
1个回答

1
这很令人惊讶,因为分层编译实际上应该加快预热速度。
您混淆了达到最高性能的时间和初始化/响应应用程序的时间。
+分层
解释器(第0层)-> C1(第1-3层)-> C2(第4层)
重型C2工作被推迟到以后的时间点
在C1编译代码中花费更多时间意味着应用程序启动后的类型文件可能更干净,从而允许更好的优化和更少的C2反编译
应用程序可以更快地提供其第一个请求/达到用户交互/短暂的Java执行更快完成
-分层
解释器-> C2
热代码可能更快地达到最高性能
初始化和温暖代码可能需要更长时间
较少的剖析时间可能在某些情况下导致略微次优的代码
另一个要尝试的是编译器线程数(CICompilerCount)。性能权衡很复杂,因此简单地对各种设置进行基准测试可能会有所帮助。

更新:无法再现Java 8预热时间的显著差异。这一定是由于外部环境的差异造成的。 - Suresh Mahalingam
1
我们仍然看到Java 8稳定状态需要10-15%的时间,但没有像数量级差异那样严重。我们已经成功完全转换到Java 8。转换后,我们发现运行时出现了Metaspace耗尽的问题,因为它在不断增长。限制Metaspace会导致运行时错误,而不限制则会被Linux OOM Killer杀死Java进程。问题最终是由于旧的10g Oracle JDBC驱动程序引起的,并且在升级到Oracle网站上推荐的最新11g驱动程序后消失了。 - Suresh Mahalingam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接