jvm的代码缓存耗尽致使性能降低

  在没遇到这个问题以前,我对JVM的解释模式与编译模式的代码性能相差有多大,是没有感受的,只是以为编译模式会比解释模式性能好那么一点点吧。html

可是经历过此次之后,让我对JVM的即时编译产生了兴趣。先来看看这个问题的背景:c++

  大概是4年前,个人团队里有一个PM找我说他们遇到一个很奇怪的问题,在性能测试的时候,有几个不一样的测试场景混合在一块儿进行压力测试,有时会出现测试几十几分钟之后性能会降低的很厉害,一旦出现性能降低之后,性能再也回不到刚开始测试的水平。奇怪的是:它不是必现的,并且若是只是某1个或者2个场景一块儿测试的话,不会出现。缓存

  由于不是网上问题,因此我有时间坐下来好好分析,先安排老思路排查,按我遇到的经验通常性能瓶颈是某些资源遇到了瓶颈,这些瓶颈能够是磁盘IO、网络IO、CPU、内存等,而后使用相应的Linux命令一一排查。在排查到CPU的时候,发现CPU比较高,而后使用jstack屡次取堆栈进行分析,可是发现每次堆栈的栈顶都不太同样,可是从栈顶再往下看,能看到都是停留在咱们使用的一个商用软件Volantis MCS的堆栈上。Volantis MCS即Volantis Multi Channel Server,它的做用是使用某种开发语言开发一个页面,在用户经过手机访问时会根据用户的手机的User-Agent自动转换成最适合手机展现的xhtml页面,就是咱们常说的终端适配了。服务器

  它与咱们以往的不同的是之前出现的CPU高通常堆栈都是集中在某一个或者几个方法上,而此次是分散在不少处,有点犯难了。网络

  因为是商用软件,没有源代码,我只能把取到一些典型的堆栈记下来,而后反编译代码,看到常常在jstack上处于Runnable的栈顶的代码并非很复杂的逻辑,只有一些基本的字符串、+-*/这样的运算。由于性能压测tps比较高,直接使用JProfiler工具的话,性能是压不上去的,只能拿出个人杀手锏了: 把class反编译之后,本身加了一些统计性能的代码,并按期的打印出来。虽然方法有点土,可是直接有效。工具

  打印出统计日志之后,就发现问题所在了,一样没有任何IO操做的方法,在出现问题前调用一次在3~5ms,而出现问题之后这个方法平均时长为20~30ms。难道是输入不同吗?随后又增长日志把输入也打印出来,发现彻底同样。性能

  一样的输入,一样的代码,居然性能相差这么大,难道是机器上有其它进程(线程性能影响),排查了也没有呀。学习

  这时忽然灵光一现,是否是由于这段代码在必定状况下没有编译成本地代码,而是在解释模式下运行的?是否是编译代码时也有缓存大小,在网上查了一下我所用的JDK版本的默认的代码缓存是64M,在官方找到了对应版本的配置,并根据网上的信息若是发生这种问题,会在gc日志会打印一句warning,具体的warning是什么忘记了。反正咱们的机器的内存配置通常至少都是32G,代码缓存配置为128M也不为过,配置了之后不论怎么测试都OK了.测试

   回过头了想一想为何会有时出现有时没有?猜想缘由大概是这样的,由于咱们应用代码量很是大,使用了不少第三方软件,特别是Volantis MCS这样很是耗CPU的组件执行的频率如此之频繁,在某一种场景下,若是先测试某个流程会致使那个流程中大量的代码被转换成本地代码,而后再执行这些很是频繁的代码的时候代码的缓存由于耗尽了,就只能采用解释的方式执行。优化

  事情到这里其它我最感兴趣的地方才刚开始:

  一、解释模式与编译模式性能究竟相差多少?

  二、为何编译之后的代码性能这么高?

  第一个问题我作了测试,把JVM的配置修改成纯解释模式,原来几分钟启动的应用,等了有20分钟左右尚未彻底启动起来,要知道咱们用的服务器通常至少都是4核心的。第二个问题,下载了openjdk的代码,看了x86的c++的代码,发现太复杂了,当时放弃继续研究。直到去年的时候,我离开华为的时候有了一些本身的时间,本身买了一本《Hotspot实战》并在iteye上有一个高级虚拟机的组的一些前阿里大神的一些文章,结合openjdk 8的代码,才慢慢对编译的原理有些感受。为何性能相差这么大,个人理解解释模式采用套用代码调用的模板,每个指令选择一个template,把执行的template的汇编代码打印出来,能够看出来一个很简单的指令都会生成一堆指令。而编译模式有C1和C2 2层优化(http://hllvm.group.iteye.com/group/topic/39493),JVM先把汇编指令转换成一种中间的代码格式ad,再采用传统的编译器的优化优化技术,这些优化技术是集国外的各大神的技术精髓,因此它从新生成的代码比你手工写的代码质量高就一点不奇怪了。

  随着逐步深刻,发现原来JVM的GC又是一块宝藏。话题有点扯远了,发现本身懂的太少了,JVM里面好玩的东西太多了,学习中...

相关文章
相关标签/搜索