2016-11-09 32 views
3

有沒有人很好地理解/解釋瞭如何使用Chrome(V8)在JavaScript中確定字符串的堆大小?瞭解Javascript/V8中的字符串堆大小

的我在堆轉儲看到一些例子:

1)相同的2個字符串的多個拷貝(即「DT」)具有不同@對象ID的所有指定爲OneByteStrings。 heapdump說每個副本都有一個淺的保留大小爲32字節的&。目前還不清楚兩個字節的字符串是如何保留大小爲32以及爲什麼字符串不會被屏蔽的。

2)長度爲78個字符的長對象路徑字符串。所有字符都是utf8中的單個字節。它被分類爲一個InternalizedString。它有一個184字節的保留大小。即使使用2字節的字符編碼,仍然不會考慮剩餘的28個字節。爲什麼這些路徑佔用太多空間?我可以想象另外4個字節(可能是8個)用於地址,另外4個字節用於存儲字符串長度,但即使採用2字節字符編碼,仍然會留下16個字節。

回答

4

內部,V8擁有字符串許多不同表示:

  • SeqOneByteString:最簡單的,包含了一些頭字段,然後字符串的字節(而不是UTF-8編碼,只能包含字符前256個unicode代碼點)
  • SeqTwoByteString:相同,但每個字符使用兩個字節(使用代理對錶示不能用兩個字節表示的unicode字符)。
  • SlicedString:其他字符串的子字符串。包含指向「父」字符串的指針以及偏移量和長度。
  • ConsString:添加兩個字符串(如果超過一定大小)的結果。包含指向兩個字符串的指針(它們本身可以是任何這些類型的字符串)。
  • ExternalString:用於從V8外部傳入的字符串。

「內部化」只是一個標誌,實際的字符串表示可以是以上任何一種。

所有這些都有一個共同的父類String,其父爲Name,其父爲HeapObject(這是V8堆中分配的對象的V8類層次結構的根)。

  • heapobject有一個字段:指向它的Map的指針(這是對這些here的一個很好的解釋)。
  • 名稱添加一個附加字段:散列值。
  • 字符串添加另一個字段:長度。

在32位系統上,每個系統都是4個字節。在64位系統上,每個系統都是8個字節。

如果您使用的是64位系統,那麼SeqOneByteString的最小大小爲32個字節:上述頭字段的最小大小爲24個字節,並且至少爲字符串數據的一個字節,四捨五入爲8.

關於你的第二個問題,很難說具體到底發生了什麼。這可能是因爲字符串使用了2字節表示形式,並且其頭部字段的大小超出了您所期望的大小,或者可能是ConsString或SlicedString(其保留大小將包含它指向的字符串至)。

V8在大部分時間內沒有內部化字符串 - 它將字符串常量和在解析過程中找到的標識符名稱以及用作對象屬性鍵的字符串(可能還有其他一些情況)內化。