首先在了解安卓N的混合编译特性之前先明白静态编译与动态编译:(直接引用别人的解释)
静态编译优化和动态编译优化最大的不同是他们在编译时所得到的信息量的不同。静态编译在运行程序之前就把所有的执行代码编译完,这时编译器所接受的编译信息量是不够多的。比如说:某个函数是否是大量地被调用了,函数的实参是不是一直是一个常数,等等。
动态编译之于静态编译,缺点是它需要即时编译代码,但是有一个优点---编译器可以获得静态编译期所没有的信息。比如:通过运行时的profiling可以知道哪些函数是被大量使用的。在哪些execution path上哪些函数的参数一直都没有变,等等。不要小看这些信息,当即时编译器了解这些信息之后可以在短时间内编译出比静态编译器更优质的二进制码。举例来说,一般程序也遵循90-10原则,即运行时的90%里计算机是在处理其中10%的代码,寻找到这些执行热点代码进行深度优化能得到比静态编译更好的性能(因为已知更多信息量)
即时编译的开销非常大,暂时还不能超越静态编译的总体性能。
在安卓4.4之前是采用即时编译,安卓5.0时代正式使用静态编译将代码直接转换成elf直接执行的机器语言(类比于x64的exe),此时但就执行效率来讲安卓跟上了ios(编译代码质量与编译方式有很大联系难以比较),都是直接执行的机器语言了。在安卓N时代,采取了进一步的优化,代码刚开始是不进行dexoat的,而是像以前安卓4.0时代一样执行,所以此时安装速度很快。随着应用的使用,安卓内核使用一个profile函数收集使用代码的各种信息,存储在profiles文件夹,当收集到一定量之后,达到系统的触发条件,进行dex2oat编译成机器码直接执行。这个过程不是一次性的,而是可以进行多次的,随着收集到应用运行时的代码各种信息越多,那么代码编译的质量就越高,效率越高,不断更新编译的机器语言。(但是有些应用,比如万恶的微信,还有国产其他毒瘤,一些优化由于他为了加各种无用的功能,忽视标准,导致更新时导致优化无法进行,这时需要卸载重装而不能直接更新)。同时安卓N还生成一个art索引文件,预加载与缓存提升应用性能,进一步加快应用的启动速度与运行性能。所以这种优化没有极限,google能够进一步提高性能,而ios的静态语言却受到限制。一个动态语言有着静态语言所没有的各种优势,必然是将来程序语言发展的方向。伴随着强大的需求,即时编译器在将来也会更加强大。
静态编译优化和动态编译优化最大的不同是他们在编译时所得到的信息量的不同。静态编译在运行程序之前就把所有的执行代码编译完,这时编译器所接受的编译信息量是不够多的。比如说:某个函数是否是大量地被调用了,函数的实参是不是一直是一个常数,等等。
动态编译之于静态编译,缺点是它需要即时编译代码,但是有一个优点---编译器可以获得静态编译期所没有的信息。比如:通过运行时的profiling可以知道哪些函数是被大量使用的。在哪些execution path上哪些函数的参数一直都没有变,等等。不要小看这些信息,当即时编译器了解这些信息之后可以在短时间内编译出比静态编译器更优质的二进制码。举例来说,一般程序也遵循90-10原则,即运行时的90%里计算机是在处理其中10%的代码,寻找到这些执行热点代码进行深度优化能得到比静态编译更好的性能(因为已知更多信息量)
即时编译的开销非常大,暂时还不能超越静态编译的总体性能。
在安卓4.4之前是采用即时编译,安卓5.0时代正式使用静态编译将代码直接转换成elf直接执行的机器语言(类比于x64的exe),此时但就执行效率来讲安卓跟上了ios(编译代码质量与编译方式有很大联系难以比较),都是直接执行的机器语言了。在安卓N时代,采取了进一步的优化,代码刚开始是不进行dexoat的,而是像以前安卓4.0时代一样执行,所以此时安装速度很快。随着应用的使用,安卓内核使用一个profile函数收集使用代码的各种信息,存储在profiles文件夹,当收集到一定量之后,达到系统的触发条件,进行dex2oat编译成机器码直接执行。这个过程不是一次性的,而是可以进行多次的,随着收集到应用运行时的代码各种信息越多,那么代码编译的质量就越高,效率越高,不断更新编译的机器语言。(但是有些应用,比如万恶的微信,还有国产其他毒瘤,一些优化由于他为了加各种无用的功能,忽视标准,导致更新时导致优化无法进行,这时需要卸载重装而不能直接更新)。同时安卓N还生成一个art索引文件,预加载与缓存提升应用性能,进一步加快应用的启动速度与运行性能。所以这种优化没有极限,google能够进一步提高性能,而ios的静态语言却受到限制。一个动态语言有着静态语言所没有的各种优势,必然是将来程序语言发展的方向。伴随着强大的需求,即时编译器在将来也会更加强大。