inside the V8 engine + 5 tips on how to write optimized code
兩週前咱們開始了js深刻了解以及它如何的工做原理的研究:咱們認爲經過了解js的代碼構建和他們的運行機制能夠寫出更好的代碼和app。
前面的博文主要是js引擎概述,運行和堆棧。第二篇會深刻谷歌V8的js引擎部分,咱們也會提供一點點關於如何編寫更好的js代碼的建議-最好java
js引擎是一個程序或者執行js代碼解析器。js引擎能夠實現爲一個標準的翻譯,或者以某種形式將js代碼即時編譯成字節碼。 下面是流行的js執行引擎清單列表:node
由google開發V8引擎是開源的,用c++編寫。這個引擎用於Google Chrome。不像其餘的引擎,當前流行的node.js也是基於V8運行。 c++
當開始執行js代碼,v8使用full-codegen直接解析js翻譯成機器碼,沒有任何轉換。這容許它開始執行機器代碼很是快。注意v8不使用中間字節碼錶示這種方式不須要翻譯。web
當你的代碼運行一段時間後,解析器線程會彙集足夠的數據告訴咱們哪些方法必須優化。 接下來,Crankshaft開始在另外一條線程上優化。它將js抽象語法樹(syntax tree )轉換成一個叫Hydrogen 的高級靜態單元分配表示 (SSA) ,並且嘗試去優化 Hydrogen這個圖。大多數的優化是在這級完成的。編程
首次優化儘量多的提早嵌入代碼。代碼嵌入是將使用函數的地方(調用函數的那一行)替換成被調用函數的本體。這個簡單的步驟可使接下來的優化更有意義。 瀏覽器
js是一個基於原型鏈的語言:它沒有類和對象是經過克隆產生的。js也是一個動態編程語言,這意味着在對象實力化之後能夠很簡單增長或者移除屬性。 大多數js解析器使用相似字典同樣的結構(基於散列函數) 去儲存對象屬性值在內存中的地址。這種構造使js在檢索對象屬性值上比其餘相似java,c++等動態語言,花費更大的計算量。在java中,全部的對象屬性在編譯以前都已經被固定的對象容器決定。並且在運行時不能夠動態的添加或者刪除屬性。(c++的動態類型是另外一個話題)。結果,每個屬性的值可以以連續的buffer儲存在內存中,在每一個屬性值之間有一個偏移量。這個偏移量的長度很容易根據屬性類型決定。然而在js中這是不可能的,由於js的屬性值能夠在運行時改變。 由於使用字典去查找對象屬性在內存中的地址的效率很低,V8使用了一個不一樣的方法代替:隱藏類。隱藏類與在java等語言中使用的固定對象佈局的工做方式相似,除了他在運行時被建立。來讓咱們看一下真實的代碼:緩存
function Point(x,y){
this.x = x;
this.y = y;
}
var p1 = new Point(1,2);
複製代碼
一旦 new Point(1,2) 被調用,V8會建立一個名爲 C0 的隱藏類。 session