真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

如何分析JS引擎中的InlineCache技術

如何分析JS引擎中的Inline Cache技術,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

創(chuàng)新互聯(lián)公司2013年至今,先為荊門等服務建站,荊門等地企業(yè),進行企業(yè)商務咨詢服務。為荊門企業(yè)網(wǎng)站制作PC+手機+微官網(wǎng)三網(wǎng)同步一站式服務解決您的所有建站問題。

01
 引例

     

     
function Point(x,y) {
this.x = x;
this.y = y;
}
var p = new Point(0, 1);
var q = new Point(2,3);
var r = new Point(4,5);

為了避免API調用不穩(wěn)定因素的影響,通過修改V8源碼,在內部插入時間戳的方式。在3.2G 8核機器上,分別測試三次調用new Point(x,y)時執(zhí)行this.x=x這個語句耗時,結果如下表所示。

執(zhí)行代碼this.x=x耗時統(tǒng)計
var p = new Point(0,1);4.11ns
var q = new Point(2,3);6.63ns
var r = new Point(4,5);0.65ns

從表中的結果可以看出,事實并非想象中的從第二次執(zhí)行開始,速度就會變快,相反,第二次比第一次還要慢,到第三次的時候速度才會變快。本文后面會通過分析V8 IC機制來解釋為什么第二次速度最慢,第三次執(zhí)行速度又變快的原因。

02      
 問題分析


1. 對象的隱藏類(Hidden Class)

由于JavaScript對象沒有類型信息,幾乎所有JS引擎都采用隱藏類(Hidden Class/Shape/Map等)來描述對象的布局信息,用以在虛擬機內部區(qū)分不同對象的類型,從而完成一些基于類型的優(yōu)化。

V8對JavaScript對象都使用HeapObject來描述和存儲,每一種JavaScript對象都是HeapObject的子類,而每個HeapObject都用Map來描述對象的布局。對象的Map描述了對象的類型,即成員數(shù)目、成員名稱、成員在內存中的位置信息等。

上述源碼中對象p、q、r都是由同一個構造函數(shù)Point生成,因此他們具有同樣的內存布局,可以采用同一個Map來描述。

2. 隱藏類變遷(Map Transition)

因為JavaScript是高度動態(tài)的程序設計語言,對象的成員可以被隨意動態(tài)地添加、刪除甚至修改類型。因此,對象的隱藏類在程序的運行過程中可能會發(fā)生變化,V8內部把這種變化叫隱藏類變遷(Map Transition)。

以上文代碼為例,當Point function被聲明時,V8就會給Point創(chuàng)建隱藏類map0,由于暫時還沒有屬性,因此map0為空。當執(zhí)行this.x=x時,V8會創(chuàng)建第二個Hidden Class map1,map1是基于map0,并且描述了屬性x在內存中的位置,此時this對象的Hidden Class會通過Map Transition變?yōu)閙ap1。當執(zhí)行this.y=y時,會重復前面的操作,一個新的Hidden Class map2會被創(chuàng)建,此時this對象的Hidden Class被更新為map2。this對象的Map從map0變?yōu)閙ap1,再變成map2的過程就叫做Map Transition。圖一描述了Point類對象創(chuàng)建過程中Map Transition的過程。  

如何分析JS引擎中的Inline Cache技術

Map Transition示意圖

3. 類型反饋向量(type feedback vector)  

前面已經提到IC機制的原理是:對于某代碼語句比如this.x=x,比較上次執(zhí)行到該語句時緩存的Map和對象當前的Map是否相同,如果相同則執(zhí)行對應的IC-Hit代碼,反之執(zhí)行IC-Miss代碼。那么V8是如何組織被緩存的Map和IC-Hit代碼?以上文代碼為例,V8會在Point函數(shù)對象上添加一個名為type_feedback_vector的數(shù)組成員,對于該函數(shù)中的每處可能產生IC的代碼,Point對象中的type_feedback_vector會緩存上一次執(zhí)行至該語句時對象的Map和對應的IC-Hit代碼(在V8內部稱為IC-Hit Handler)。上文中的Point函數(shù)中有兩處可能產生IC的語句,this.x=x和this.y=y。假設某次執(zhí)行至this.x=x時,對象this的Map是map0,執(zhí)行至this.y=y時this的Map是map1,那么Point對象的type_feedback_vector數(shù)據(jù)內容如下所示:

數(shù)組下標IC對應的源碼緩存的Map和對應的IC-Hit Handler
0this.x=x
1this.y=y

簡單來說,type_feedback_vector緩存了Map和與之對應的IC-Hit handler,這樣IC相關的邏輯簡化為只需要通過訪問type_eedback_vector就可以判斷是否IC Hit并執(zhí)行對應的IC-Hit Handler。

4. IC狀態(tài)機

為了描述V8中IC狀態(tài)的變化情況,本節(jié)將以狀態(tài)機的形式描述V8中最常見IC種類的狀態(tài)變化情況。V8中最常用 的IC分為五個狀態(tài),如圖二所示。初始為uninitialized狀態(tài),當發(fā)生一次IC-Miss時會變?yōu)閜re-monomorphic態(tài),再次IC-Miss會進入monomorphic態(tài),如果繼續(xù)IC-Miss,則會進入polymorphic狀態(tài)。進入polymorphic之后如果繼續(xù)IC-Miss 3次,則會進入megamorphic態(tài),并最終穩(wěn)定在megamophic態(tài)。

如何分析JS引擎中的Inline Cache技術

IC狀態(tài)機

引例中代碼會涉及到IC狀態(tài)機的前三種狀態(tài)。

以Point函數(shù)走紅this.x=x語句為例,第一次執(zhí)行時,由于Point.type_feedback_vetor為空,因此此時會發(fā)生IC-Miss,并將該處IC狀態(tài)從uninitialized設置為pre-monomorphic,IC-Miss Handler會分析出此時this對象的Map中不包含屬性x,因此會添加成員x,接著會發(fā)生Map Transition,即前文提到的this對象的隱藏類從map0變?yōu)閙ap1。由于考慮到大部分函數(shù)可能只會被調用一次,因此V8的策略是發(fā)生第一次IC-Miss時,并不會緩存此時的map,也不會產生IC-Hit handler;

第二次調用構造函數(shù)執(zhí)行this.x=x時,由于Point.type_feedback_vector仍然為空,因此會發(fā)生第二次IC-Miss,并將IC狀態(tài)修改為monomorphic,此次IC-Miss Hanlder除了發(fā)生Map Transition之外,還會編譯生成IC-Hit Handler,并將map0和IC Hit Handler緩存到Point.type_feedback_vector中。由于此次IC-Miss Handler需要編譯IC-Hit Handler的操作比較耗時,因此第二次執(zhí)行this.x=x是最慢的;

第三次調用構造函數(shù)中this.x=x時,發(fā)現(xiàn)Point.type_feedback_vector不為空,且此時緩存的map0與此時this對象的Map也是一致的,因此會直接調用IC-Hit Handler來添加成員x并進行Map transition。由于此次無需對map0進行分析,也無需編譯IC-Hit Handler,因此此時執(zhí)行效率比前兩次都高。

至此,已經解釋清楚為什么V8執(zhí)行構造函數(shù)時,第二遍最慢而第三遍最快的原因。
5. Polymorphic和Megamorphic
function f(o) {

  return o.x;
}

f({x:1}) //pre-monomorphic

f({x:2}) //monomorphic

f({x:3, y:1}) // polymorphic degree 2

f({x:4, z:1}) // polymorphic degree 3

f({x:5, a:1}) // polymorphic degree 4

f({x:6, b:1}) // megamorphic
上述代碼描述了圖二狀態(tài)機中polymorphic態(tài)和megamophic態(tài)的兩種情形。上面3中提到type_feedback_vector會緩存Map和IC-Hit Handler,但是如果IC狀態(tài)太多比如到達megamorphic態(tài),此時Map和IC-Hit Handler便不會再緩存在Point對象的feedback_vector中,而是存儲在固定大小的全局hashtable中,如果IC態(tài)多于hashtable的大小,則會對之前的緩存進行覆蓋。通過上述分析,可以總結得出不同IC態(tài)的性能:
  • 如果每次都能在monomorphic態(tài)IC-Hit,代碼的運行速度是最快的;
  • 在polymorphic態(tài)IC-Hit時,需要對緩存進行線性查找;
  • Megamorphic是性能最低的IC-Hit,因為需要每次對hashtable進行查找,但是megamorphic ic hit性能仍然優(yōu) 于IC-Miss;
  • IC-Miss性能是最差的;

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對創(chuàng)新互聯(lián)的支持。


當前名稱:如何分析JS引擎中的InlineCache技術
地址分享:http://weahome.cn/article/ijsjds.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部