JIT技术(HHVM中有用到)

Java编程语言和环境中,即时编译器(JIT compiler,just-in-timecompiler)是一个把Java的字节码(包括需要被解释的指令的程序)转换成可以直接发送给处理器(processor)的指令的程序。当你写好一个Java程序后,源语言的语句将由Java编译器编译成字节码,而不是编译成与某个特定的处理器硬件平台对应的指令代码(比如,Intel的Pentium微处理器或IBM的System/390处理器)。字节码是可以发送给任何平台并且能在那个平台上运行的独立于平台的代码。
   
  过去,大多数用任何语言写的程序在每个电脑平台上都必须重编译,甚至有时需要重写。Java最大的优点之一就是你只需要写和编译一次程序。在任何平台上,Java都会将编译好的字节码解释成能被特定的处理器所理解的指令。尽管如此,Java虚拟机一次只能处理一条字节码指令。在特定的系统平台上使用Java即时编译器(实际上是第二个编译器)能把字节码编译成特定系统的代码(虽然这个程序最初已经在这个平台上被编译过)。一旦代码被JIT编译器(重)编译后,它在电脑上通常就会运行地更快。
   
  即时编译器(JIT compiler)随虚拟机一起供给的,并可选使用。它把字节码编译成可立即执行的指定平台的可执行代码。Sun微系统建议,选择JIT编译器选项通常会使程序运行地更快,尤其是当某个可执行的方法被重复使用时。


二:

最早的Java建置方案是由一套转译程式(interpreter),将每个Java指令都转译成对等的微处理器指令,并根据转译后的指令先后次序依序执行,由于一个Java指令可能被转译成十几或数十几个对等的微处理器指令,这种模式执行的速度相当缓慢。
       针对这个问题,业界首先开发出JIT(just in time)编译器 。当Java执行runtime环境时,每遇到 一个新的类别(class:类别是Java程式中的功能群组),类别是Java程式中的功能群组-JIT编译器在此时就会针对这个类别进行编译(compile)作业。经过编译后的程式,被优化成相当精简的原生型指令码(nativecode) ,这种程式的执行速度相当快。花费少许的编译时间来节省稍后相当长的执行时间,JIT这种设计的确增加不少效率,但是它并未达到最顶尖的效能,因为某些极少执行到的Java指令在编译时所额外花费的时间可能比转译器在执行时的时间还长,针对这些指令而言,整体花费的时间并没有减少。

       基于对JIT的经验,业界发展出动态编译器(dynamic compiler) ,动态编译器仅针对较常被执行的程式码进行编译,其余部分仍使用转译程式来执行。也就是说,动态编译器会研判是否要编译每个类别。动态编译器拥有两项利器:一是转译器,另一则是JIT,它透过智慧机制针对每个类别进行分析,然后决定使用这两种利器的哪一种来达到最佳化的效果。动态编译器针对程式的特性或者是让程式执行几个循环,再根据结果决定是否编译这段程式码。这个决定不见得绝对正确,但从统计数字来看,这个判断的机制正确的机会相当高。事实上,动态编译器会根据「历史资料」做决策,所以程式执行的时间愈长,判断正确的机率就愈高。以整个结果来看,动态编译器产生的程式码执行的速度超越以前的JIT技术,平均速度可提高至50%。
即时编译(Just-in-time Compilation,JIT),又称动态转译(Dynamic Translation) ,是一种通过在运行时将字节码翻译为机器码,从而改善字节码编译语言性能的技术。即时编译前期的两个运行时理论是字节码编译和动态编译。 
       在编译为字节码的系统如 Limb 编程语言,Smalltalk,UCSD P-System, Perl,GNU CLISP,和 Java 的早期版本中, 源代码被翻译为一种中间表示即字节码。 字节码不是任何特定计算机的机器码, 它可以在多种计算机体系中移植。 字节码被解释着运行在虚拟机里。
动态编译环境是一种在执行时使用编译器的编译环境。 例如, 多数 Common Lisp 系统有一个编译函数,他可以编译在运行时创建的函数。
在即时编译环境下, 字节码的编译是第一步, 它将源代码递归到可移植和可优化的中间表示。字节码被部署到目标系统。 当执行代码时,运行时环境的编译器将字节码翻译为本地机器码。 基于每个文件或每个函数:函数仅仅在他们要被执行时才会被编译。
目标是要组合利用本地和字节码编译的多种优势:多数重量级的任务如源代码解析和基本性能的优化在编译时处理,将字节码编译为机器码比起从源代码编译为机器码要快得多。部署字节码是可移植的,而机器码只限于特定的系统结构。从字节码到机器码编译器的实现更容易,因为大部分工作已经在实现字节码编译器时完成。
好,说白了,JIT 在Android方面其实现实际上是在 Dalvik vm这一层,与内核是分离的,直观的表现就是几个库文件。
然后,JIT到底能提升机器多大的性能?我也不知道——不要跟我说Linpack跑多少分,学计算机的都知道,Linpack只是一个基准测试程序,测试的是机器的浮点计算能力、向量性能和高速缓存性能。Linpack只是众多基准测试的一种,它的分数代表不了任何东西。它只有一个局部的计算性能参考
        然后,为什么使用了JIT之后,Linpack的分数就能提高很多?OK,看Linpack是干什么的——有一项是测试高速缓存的,那么,使用JIT之后,一部分Dalvik的字节码(apk程序包的逻辑部分,如*.dex和*.odex)会被转译成手机CPU的指令代码,那好,这部分代码就可以进行重用,减少了编译的时间,这就相当于一个“缓存”,使得访问Dalvik字节码的次数大大降低,也就是减少了解释执行字节码的次数。要知道,解释执行字节码的速度是比较慢的,所以直接体现就是Linpack分数的提高。
       那么,JIT对我们使用的影响大么?
       准确的说,有,但不是很大,根本达不到Froyo 2.2宣传的那样(我恨IT媒体)几倍的提升。为什么?因为我们用的系统不光有逻辑(程序执行),还有UI(图形渲染),以及其他很多因素(线程调度、I/O等等),单独的JIT技术只是提高了程序代码的执行效率(还不是全部),并未对系统有全局优化的功效。如果可以的话,可以针对Linpack专门设计一个优化的虚拟机,让G2这样的机器跑到30分也是没问题的。但是实际使用的体验不会好很多




你可能感兴趣的:(JIT技术(HHVM中有用到))