原理
对于解释性语言(如JS、Python)来说,解释器将代码一行行得翻译为机器语言,边翻译边执行。而对于编译性语言(C/C++/Java)来说,编译器提前对所有代码进行编译和优化,后续执行程序的时候直接运行机器代码即可,所以编译性语言的执行效率大大高于解释性语言。
解释器运行同样的代码一次以上的时候,比如执行一个循环,解释器不得不一次又一次的进行翻译,效率非常低下。
JIT(即时编译)可以解决一部分反复翻译的问题
在 JavaScript 引擎中增加一个监视器监控着代码的运行情况,记录代码一共运行了多少次、如何运行的等信息。如果同一行代码运行了多次,这个代码段就会被送给JIT机制进行编译和优化,将编译后的机器代码保存在缓存中,下次直接执行这块机器代码即可,大大提高了一些情况下代码的执行效率。
V8引擎中使用
V8有两个编译器
- full-codegen:一个简单而且速度非常快的编译器,可以生成简单且相对较慢的机器代码。
- Crankshaft:JIT的优化编译器,可以生成高度优化的代码。
V8引擎还在内部使用多个线程
- 主线程完成预定的任务:获取你的代码,编译它然后执行它
- 一个单独的线程用于编译,当这个单独的线程优化代码时,主线程可以继续执行
- 一个Profiler线程,它会告诉运行时我们花了很多时间,使得Crankshaft能够优化它们
- 一些线程处理垃圾处理器扫描
当第一次执行JavaScript代码时,V8利用full-codegen,直接将解析的JavaScript翻译成机器代码而无需任何转换。当代码运行一段时间后,Profiler线程已经收集了足够的数据以确定哪种方法应该进行优化。接下来,Crankshaft从另一个线程开始对代码优化和缓存。
优化方法:
- 类型限定 (每次动态判断类型太耗时)
- 调用函数内联化
- 隐藏类(每次遍历查找类的属性太低效)
- 机器码缓存(将反复执行的代码翻译为机器码存在内存中,如循环递归等函数)
WebAssembly中使用
WebAssembly是一种新的字节码格式,缩写是"wasm", .wasm 为文件名后缀,是一种新的底层安全的二进制语法。
WebAssembly不算一种一门编程语言,而是一种编译机制,很多浏览器都支持WebAssembly,对WebAssembly格式的解码速度要快得多得多得多。
Python中使用
PyPy可以提供JIT。
网友评论