2015-04-24 61 views
4

我剛剛在研究Google V8 Javascript引擎的性能改進,因爲我想將它集成到我自己的項目中。V8引擎如何處理添加屬性的排序?

我現在的興趣是隱藏的課程。其基本思想是V8創建隱藏類,因爲屬性被添加到對象中,以便高效查找該屬性,從而避免字典搜索。

例如,當你創建一個名爲pPoint對象時,它會創建一個隱藏的類C0這是一個沒有屬性的類和類附加到對象:

enter image description here

聲明p.x = 0將修改的對象添加屬性,然後創建一個新指定C1x屬性可以在特定的對象中的偏移量被發現。

enter image description here

p.x因此讓後是一個比較有效的操作。

最後,執行p.y = 0將執行一個類似的操作,用結束了:

enter image description here

現在,這實際上是相當漂亮的,因爲如果你創建另一個Point對象p2,沒有新的隱藏類需要是創建,它只是被「分配」到C0。類似地,按照該順序添加xy屬性在無需創建新的隱藏類方面也是有效的。


但是這個方案有兩個潛在的問題。第一個涉及使用下面的代碼段會發生什麼:

Point p3 = new Point(); 
p3.y = 3141592653589; 
p3.x = 2718281828459; 

在我看來,這將創建兩個隱藏的類,一個與y偏移量爲零,另一個y在抵消了零偏移和x一。

這似乎有點空間低效的,因爲在這兩種情況下,最終類有一個xy所以應該能夠分享類C2,儘管你會需要交換xy的對象的要求本身。

會是什麼使得過渡映射的影響多一點控制,如確保性能是按字母順序存儲?這樣一來,無論你增加x然後y,或y然後x,你仍然會在相同的最後一節課結束。添加屬性時

這將意味着一些額外的工作,但可以大大減少隱藏類的數量。

或者是額外的工作本身可能會導致性能下降?


第二個潛在的問題是,因爲該方案的整個目的是避免在對象上的字典查找,如何移動:

For x, see offset 0 
For y, see offset 1 

進級的幫助?

在我看來,你會仍然需要查找隱藏類中的屬性名稱來獲取對象內的偏移量。

還是我錯過了什麼,沒有字典搜索的類是必需的?

+0

@Hanky,上車我修改是1968年霍頓HR,悶掉活塞以使它們輕於在每個頂部添加一個頂蓋以獲得更多壓縮。達到90英里每小時(從大約70),但引擎不久後融合。現代汽車根本就沒有樂趣,不得不插入一臺昂貴且不是非常可用的電腦來做任何事情:-) – paxdiablo

+0

哈哈,一定覺得不錯:) –

+1

也許你會覺得這有幫助:http:// www.google.com/patents/US8244775。關於交換x和y屬性的問題,我記得在v8可以正確處理這種小小的不一致的地方閱讀。但通常會產生不同的隱藏類。因爲幾乎總是以相同的順序添加屬性(通過相同的構造函數),所以在實現類似於你所建議的東西時沒有什麼意義。 –

回答

1

優化後,不需要字典搜索(對於大多數訪問)。

在屬性訪問時,v8有(希望)將屬性訪問轉換爲內聯緩存存根。這意味着在訪問x時,其身份爲x已被包含在偏移值中。所以它不再是真正的x,或者甚至x at offset 0,它只是offset 0。即使對象表示被稱爲「地圖」,它實際上只是一個偏移表。這是使財產訪問更快的原因。

當需要添加新屬性時,問題不是「當前對象具有的所有屬性加上新屬性的對象在哪裏?」這是「對於這個對象,我需要做些什麼來添加這個屬性?」在此基礎上選擇轉換。在優化代碼中,不考慮現有屬性的名稱。刪除多餘的隱藏類將需要一些相對較重的操作來找到匹配的地圖。

你的假設是顛倒財產增加創造兩個新的隱藏類是正確的。您可以通過運行帶有d8 --allow-natives-syntax下得到一些啓示:

function Point() {} 

var p = new Point(); 

var px = new Point(); 
px.x = 0x10101; 

var py = new Point(); 
py.y = 0x20202; 

var pxy = new Point(); 
pxy.x = 0x30303; 
pxy.y = 0x40404; 

var pyx = new Point(); 
pyx.y = 0x50505; 
pyx.x = 0x60606; 

var newp = new Point(); 
checkmaps(); 
newp.x = 0x70707; 
checkmaps(); 
newp.y = 0x80808; 
checkmaps(); 

function checkmaps() { 
    var sameas = []; 
    if (%HaveSameMap(newp, p)) 
    sameas.push("p"); 
    if (%HaveSameMap(newp, px)) 
    sameas.push("px"); 
    if (%HaveSameMap(newp, py)) 
    sameas.push("py"); 
    if (%HaveSameMap(newp, pxy)) 
    sameas.push("pxy"); 
    if (%HaveSameMap(newp, pyx)) 
    sameas.push("pyx"); 
    print(sameas); 
} 

輸出是:

p 
px 
pxy