V8 JavaScript引擎研究(二)高性能探祕

V8的高性能探祕

V8項目負責人Lars Bak:V8的全部優化都不是原創的。V8組合了過往對於動態語言的各類優化技術,於是具備了很是高效的性能。編程

快速屬性訪問

JavaScript是動態編程語言,這意味着能夠動態的增長或刪除對象的屬性。緩存

以往實現

大多數的JavaScript引擎都是使用相似字典的數據結構來保存一個對象的屬性,在這種結構下每次訪問一個屬性都須要動態查找其在內存中的位置。數據結構

  • 優點:

    實現簡單。編程語言

  • 劣勢:

    效率低。相對於Java、Smalltalk等語言,因爲對象的class有着固定的佈局,所以屬性在內存中有着由編譯器生成相對於對象的固定位移,所以訪問屬性要快得多,可能僅須要一條機器指令。佈局

V8的實現

爲了減小訪問屬性的耗時,V8沒有使用動態動態查找來訪問屬性。性能

V8爲每一個對象建立了一個隱藏類(Hidden Class),每當增長一個屬性時更換新的隱藏類。優化

舉例說明:this

1 function Point(x, y)
2 { 3   this.x = x; 4   this.y = y; 5 }

當調用 new Point(x, y) 時產生一個新的Point對象,V8這樣來處理:首先建立一個Point的隱藏類,在此例中假設叫C0,此時對象沒有任何屬性,初始時類是空的。在此階段,Point對象的隱藏類爲C0。spa

當執行Point裏的第一條語句 this.x = x; 建立Point對象的一個新屬性x。這時V8建立另一個基於C0的隱藏類C1,而後在C1中增長描述信息,指明Point對象擁有屬性x,並存儲在相對於Point對象的位移0處。同時更新C0的類轉移信息,指明當基於C0隱藏類的對象增長了屬性x時,此對象的隱藏類將由C0替換爲C1。在此階段,Point對象的隱藏類爲C1。指針

當執行Point裏的第一條語句 this.y = y; 建立Point對象的一個新屬性y。這時V8建立另一個基於C1的隱藏類C2,而後在C2中增長描述信息,指明Point對象也擁有屬性y,並存儲在相對於Point對象的位移1處。同時更新C1的類轉移信息,指明當基於C1隱藏類的對象增長了屬性y時,此對象的隱藏類將由C1替換爲C2。在此階段,Point對象的隱藏類爲C2。

不管什麼時候只要增長一個屬性就建立一個隱藏類,這種作法彷佛看上去很是低效,然而因爲類的轉移信息,隱藏類能夠被重用。想象一下這樣的場景,當下一次一個新的Point對象被建立後,就再也不須要建立新的隱藏類,新的Point對象將共享爲第一個Point對象所建立的一系列隱藏類,具體過程以下:

初始化一個沒有任何屬性的Point對象,此時初始的隱藏類C0適用於此對象。

當增長屬性x後,V8遵循從C0到C1的類轉移信息,而後在C1指定的位移處寫入x的值。

當增長屬性y後,V8遵循從C1到C2的類轉移信息,而後在C2指定的位移處寫入y的值。

雖然JavaScript比大多數面向對象的語言更加動態,但絕大多數JavaScript程序的運行時行爲致使了高度使用上述方法的共享結構。

  • 優點:

    不須要使用動態查找字典來訪問對象的屬性,尤爲是當建立大量相同的對象時效率大幅提高。

    可讓V8使用基於隱藏類的優化技術-內聯緩存(Inline Caching)。

  • 劣勢:

    實現略複雜。

    每次對象新增屬性都須要建立一個新的隱藏類,極端狀況下效率很是低。

內聯緩存&動態機器碼生成

V8的內聯緩存依託於隱藏類技術,這裏的內聯與C++中的內聯是兩個不一樣的概念。

當第一次執行JavaScript代碼時V8直接將其編譯成機器碼,而不產生中間的字節碼。(*Google已經發布了新的JavaScript解釋器Ignition,旨在減小內存消耗,在一些內存有限的設備上使用)

在第一次指定訪問一個給定對象的屬性的代碼時,V8會肯定此對象的隱藏類。V8預測將來在此代碼段上執行的全部對象屬性訪問都擁有相同的隱藏類,並將屬性訪問的代碼經過使用此隱藏類,打進使用內聯緩存訪問指令的補丁(一般即爲一條對內存偏移地址的訪問指令,也就是內聯的概念)。若是V8預測命中,則大大優化了屬性訪問耗時;若是V8未命中,則將打進的補丁代碼移除,從新建立隱藏類並訪問屬性。

這樣在處理大量相同類型的對象並頻繁建立和訪問時(絕大多數JavaScript代碼都是如此執行),效率將極大提高。

高效的垃圾回收實現

V8垃圾回收機制簡介

V8在運行時自動回收再也不須要使用的對象內存,也便是垃圾回收。

V8使用了全暫停式(stop-the-world)、分代式(generational)、精確(accurate)等組合的垃圾回收機制,來確保更快的對象內存分配、更短的垃圾回收時觸發的暫停以及沒有內存碎片。

V8的垃圾回收有以下幾個特色:

  • 當處理一個垃圾回收週期時,暫停全部程序的執行。
  • 在大多數垃圾回收週期,每次僅處理部分堆中的對象,使暫停程序所帶來的影響降至最低。
  • 準確知道在內存中全部的對象及指針,避免錯誤地把對象當成指針所帶來的內存泄露。
相關文章
相關標籤/搜索