聊聊 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 采用的是增量標記算法,而不是一次性