V8
聊聊 v8 引擎
参考了这位老哥的博客一共三篇part1,part2,part3
总结如下:
- v8 js 的解析执行引擎,由 google 开源,采用 c++ 编写。 chrome/nodejs 都是基于 v8 进行封装。
- js 引擎中内存的抽象,堆(Memory Heap) 和 栈(Call Stack)
- 堆用于存放数组,对象等数据结构,栈则是原生类型,方法的调用也是放栈,LIFO,栈溢出等等。
- 并发(Concurrency)与事件循环(Event Loop),js 是单线程的,所以,不存在严格意义上的并发。它的异步是通过事件循环实现的。宏任务,微任务。
- 与 v8 类似的 js 引擎,例如 SpiderMonkey (firefox 内核,Netscape 开发,),JavascriptCore (Safari 内核开源), Chakra(js9 IE 内核),Chakra(js, IE Edge 内核)
- v8 的特点,
- 它的出现是为了提高 js 在浏览器中执行的性能。它将 js 翻译成更加高效的机器语言(Machine Code),而不是采用解析器。并且这种编译是发生在执行过程中(Just In Time)JIT 编译器。SpiderMonkey 也是这样的。区别是 v8 不会产生字节码或者任何中间代码。
- v8 的构成与工作流程
- v5.9 之前,v8 拥有两个编译器full-codegen, Crankshaft,
- full-codegen: 它是一个 simple and fast 编辑器,产生相对简单并且相对慢一点的机器代码
- Crankshaft: 它是一个复杂的优化的编译器(JIT),产生高度优化的代码
- v8 的工作线程
- v8 内部采用多个线程协同工作,第一个是主线程,它就是简单的读,编译,执行代码。
- v8 还有一个优化线程,主要的工作就是优化代码。
- v8 profile 线程,它会告诉运行时(runtime),哪个方法运行花费了多少时间。
- v8 还有一些额外的线程用于 gc, 垃圾回收。
- 基于上面的介绍,v8 工作的时候,主线程先工作,它采用full-codegen编译器来解析执行 js,这个没有优化代码,但会让我们的代码快速启动。然后,profile 线程会记录方法花费的时间,从而发现那些需要优化的方法。这个时候优化线程会采用 Crankshaft 编译器优化代码。Crankshaft会将 js 语法树翻译成一个static single-assignment SSA也叫Hydrogen,然后优化这个Hydrogen这个可以理解为 v8 内部的 js 抽象。
- v8 优化代码一般采用哪些计数
- inline, 也就是将方法的调用,摊平,这样节省了入栈出栈的开销
- hiddenClass, 由于 js 是动态类型,所以对象的寻址空间与 c#,java 不一样。
- inline caching, 针对用同样的参数类型去调用同样的方法的场景,会有一个优化。其实是 inline 与 hiddenClass 的集合优化。方法调用用 inline,参数的类型用 hiddenClass
- gc
- v8 采用的是 mark-and-sweep 算法来清除内存空间。marking phase 会堵塞 js 的执行。v8 采用的是增量标记算法,而不是一次性