ASP源码.NET源码PHP源码JSP源码JAVA源码DELPHI源码PB源码VC源码VB源码Android源码
当前位置:首页 >> 系统运维 >> Java性能优化指南系列三):理解JIT编译器

Java性能优化指南系列三):理解JIT编译器(1/17)

来源:网络整理     时间:2016-07-14     关键词:

本篇文章主要介绍了" Java性能优化指南系列三):理解JIT编译器",主要涉及到方面的内容,对于系统运维感兴趣的同学可以参考一下: 即时编译器概述编译器在编译过程中通常会考虑很多因素。比如:汇编指令的顺序。假设我们要将两个寄存器的进行相加,执行这个操作一般只需要一个CPU周期;但是在相加之前...

即时编译器概述

  • 编译器在编译过程中通常会考虑很多因素。比如:汇编指令的顺序。假设我们要将两个寄存器的值进行相加,执行这个操作一般只需要一个CPU周期;但是在相加之前需要将数据从内存读到寄存器中,这个操作是需要多个CPU周期的。编译器一般可以做到,先启动数据加载操作,然后执行其它指令,等数据加载完成后,再执行相加操作。由于解释器在解释执行的过程中,每次只能看到一行代码,所以很难生成上述这样的高效指令序列。而编译器可以事先看到所有代码,因此,一般来说,解释性代码比编译性代码要慢。不过,解释性代码具有可移植性的优势。
  • Java的实现在解释性和编译性之间进行了折中。Java代码是编译性的,它会被编译成一个平台独立的字节码程序。JVM负责加载、解释、执行这些字节码程序,在这个过程中,还可能会将这些字节码实时编译成目标机器码,以便提升性能。
  • 在本章中,我们主要关注JVM是如何解释、执行、编译字节码的。

编译热点代码

  • JVM在解释执行字节码的时候,不会立即对它进行编译。主要原因有两个:
    • 如果代码只执行一次,对代码进行编译得不偿失(编译之后还要执行代码)。
    • 代码执行的次数越多,JVM可以获取到的信息就越多。JVM就可以在编译代码的时候采用更多的优化手段。比如:JVM经常执行equals()方法,b = obj1.equals(obj2)JVM需要根据obj1找到它的类型,然后才知道应该执行那个equals函数。这个过程是比较费时的,为了加快执行速度,编译代码的时候可以将类型查找的过程优化掉,直接执行String.equals(obj2)。不过,在实际代码中,可能不会这么简单,obj1的类型会发生变化。但是只要代码执行次数够多,优化后,性能就会有比较大的提升。

基本调优:ClientServer

  • 即时编译器有两种类型,clientserver一般情况下,对编译器进行优化,唯一要做的就是选择那一类编译器。
  • 可以通过在启动java的命令中,传入参数(-client-server)来选择编译器(C1C2)。这两种编译器的最大区别就是,编译代码的时间点不一样。client编译器(C1)会更早地对代码进行编译,因此,在程序刚启动的时候,client编译器比server编译器执行得更快。而server编译器会收集更多的信息,然后才对代码进行编译优化,因此,server编译器最终可以产生比client编译器更优秀的代码。
  • 可能大家都有一个困扰,JVM为什么要将编译器分为clientserver,为什么不在程序启动时,使用client编译器,在程序运行一段时间后,自动切换为server编译器?其实,这种技术是存在的,一般称之为: tiered compilationJava7 Java 8可以使用选项-XX:+TieredCompilation来打开(-server选项也要打开)。在Java 8中,-XX:+TieredCompilation默认是打开的。

启动优化

  • 对于不同类型的应用,使用不同编译器的启动时间:
                   Java性能优化指南系列三):理解JIT编译器

可以看到,对于中等大小的GUI应用,使用client编译器,启动时间最短,有将近38.5%的提升。对于大型应用,使用各种编译器的启动时间差别不大。

批处理应用优化

  • 下图是对第2章中股票应用的性能测试结果,第1列是股票的个数:
                     Java性能优化指南系列三):理解JIT编译器

观察上图,可以得出以下结论:

相关图片

相关文章