Java JIT编译:不仅仅是个流行词

最近我遇到了一个Java产品性能问题,强迫我重新熟悉并且深感Java即时(JIT)编译器对我的帮助。大多数Java开发者和支持人员都听说过JVM运行时性能优化,但是究竟有多少人真正理解并从中受益?

本文将会分享我曾经遇到的一个问题及解决过程,并附带了新虚拟机服务器的配置过程(扩容和水平扩展工程)。

为了更深入地讨论JIT,我推荐下列文章:

JIT编译概述:

JIT编译本质上是改进Java应用程序运行时性能的过程。

下图展示了JVM不同层次间的交互,描述了高层次的流程:

  1. Java源码通过编译器转为平台无关的字节码(bytecode)或Java class文件。
  2. 在启动Java应用程序后,JVM会在运行时加载编译后的类并通过Java解释器执行适当的 语义计算。
  3.  当开启JIT时,JVM会分析Java应用程序的函数调用并且(达到内部一些阀值后)编译字节码为本地更高效的机器码。JIT流程通常为最繁忙的函数调用提供更高的优先级。
  4. 一旦函数调用被转为机器码,JVM会直接执行而不是“解释执行”。
  5. 上述过程会在程序运行过程中不断提高性能。

 

案例分析

现在要介绍一下我之前提到的项目背景。项目的主要目标是为产品环境添加一台新的IBM P7 AIX 虚拟服务器以提高平台性能。下面是平台的一些参数:

  • Java EE服务器:IBM WAS 6.1.0.37 & IBM WCC 7.0.1
  • OS:AIX 6.1
  • JDK:IBM J2RE 1.5.0 (SR12 FP3 +IZ94331) @64-bit
  • RDBMS:Oracle 10g
  • 平台类型:中间层和批处理

为了达到现有应用程序的性能水平采购了同样配置的硬件,AIX OS和其他IBM软件也都安装了和产品环境相同的版本。

下面的清单是所有为了确认应用程序性能一致需要验证的内容:

  • 硬件规格(CPU核、物理内存、存储器域网等)
  • OS 版本和补丁级别,包括AIX内核参数
  • IBM WAS & IBM WCC版本、补丁级别,包括调整参数
  • IBM JRE版本、补丁级别和调整参数(启动参数、Java堆大小等)
  • 还要仔细设置网络连接和性能

在新产品构建服务器安装完成后,需要进行功能测试确保在线和批处理程序性能良好。

然而,在第一天运行产品时发现了一个重大的性能问题。你可以看到一组性能数据汇总:

产品服务器
操作运行时间
处理容量(# 请求)
CPU %
(均值)
中间件健康程度
现有服务器 10 hours 250 000 (基线) 20% 健康
新服务器 10 hours 50 000   -500% 80%  +400% 大量占用线程

正如你从上面看到的,第一天产品的性能非常恐怖。不仅是新产品服务器处理的请求数很少,而且物理资源的利用率比如CPU百分比与现有的产品服务器相比超出太多。

这样的情形让人非常迷惑,要知道之前花费了大量的时间确保新服务器和现有服务器保持一致。这个节点上,另一组核心人马介入调查以解决性能问题。

排错:找到罪魁祸首

排错小组兵分两路来排查下面两个方面:

  • 确认IBM WAS容器CPU占用过高的原因,并且比较新服务器和现有服务器的CPU占用率
  • 对新服务器和现有服务器上的文件及数据进行比较

为了寻找CPU占用率高的原因,我们在IBM WAS和IBM WCC上通过IBM JVM进行AIX CPU线程分析。正如你从下面截图里看到的那样,很多线程的使用率在5-20%之间。在现有的服务器上运行分析,结果CPU线程占用率只有5%。

 

结论:

同类型的业务流程CPU占用率是现有服务器的3到4倍。

为了理解整个处理过程,JVM线程转储捕获了每个线程在同一时刻的数据。在我们审查了整个JVM(Java Core)转储的数据之后,马上意识到JIT没有启用!通过在JVM进程上运行java –version命令确认了问题。

这个发现非常重要,尤其是在现有的产品服务器上看到JIT是启用状态。与此同时,另一个负责比较文件的小组发现运行应用程序的AIX用户的环境变量有所不同。这些比较在之前的缺陷分析中被忽略掉了。他们的成果是发现新的AIX服务器上多出了下面一行:

JAVA_COMPILER=NONE

根据IBM的文档,加上这个环境变量会禁用JIT。

复杂的根源分析,简单的解决方法

为了理解在我们的运行环境下禁用JIT带来的影响,不得不去弄懂它的含义。禁用JIT本质上意味着整个JVM现在都运行在解释模式。对我们的应用程序而言,完全运行在解释模式不仅会明显降低应用的吞吐量,还会增加对服务器CPU的占用率即每个请求/线程会是JIT的3到4倍CPU占用率(请记住,当JIT启用时,JVM会直接调用机器或本地代码)。

As expected, the removal of this environment variable along with the restart of the affected JVM processes did resolve the problem and restore the performnance level.

为你的应用评估JIT带来的好处

希望你会喜欢这个案例以及对JVM JIT编译流程的简短回顾。为了理解你的Java应用程序不使用JIT会带来的影响,我推荐你做下面的实验:

  • 在启用JIT的情况下对应用进行负载测试,获取一些基线数据比如CPU占用率、响应时间、请求等
  • 禁用JIT
  • 重做上面的测试并比较结果
原文链接: javacodegeeks 翻译: ImportNew.com - 唐尤华
译文链接: http://www.importnew.com/5270.html
[ 转载请保留原文出处、译者和译文链接。]

关于作者: 唐尤华

我喜欢程序员,他们单纯、固执、容易体会到成就感;面对压力,能够挑灯夜战不眠不休;面对困难,能够迎难而上挑战自我。他们也会感到困惑与傍徨,但每个程序员的心中都有一个比尔盖茨或是乔布斯的梦想“用智慧开创属于自己的事业”。我想说的是,其实我是一个程序员。(新浪微博:@唐尤华

查看唐尤华的更多文章 >>



相关文章

发表评论

Comment form

(*) 表示必填项

还没有评论。

跳到底部
返回顶部