了解Javascript / V8中的字符串堆大小

时间:2016-11-09 17:06:51

标签: javascript string v8

有没有人对使用Chrome(V8)的Javascript中如何确定字符串的堆大小有很好的理解/解释?

我在堆转储中看到的一些示例:

1)具有不同@对象ID的相同2个字符串(即" dt")的多个副本全部被指定为OneByteStrings。 heapdump表示每个副本都有一个浅的&保留大小为32个字节。目前还不清楚两个字节的字符串是如何保留大小为32的,以及为什么这些字符串似乎没有被实习。

2)长对象路径字符串,长度为78个字符。所有字符都是utf8中的单个字节。它被归类为InternalizedString。它有一个184字节的保留大小。即使使用2字节字符编码仍然不能解释剩余的28个字节。为什么这些路径字符串占用了这么多空间?我可以想象另外4个字节(可能是8个)用于地址,另外4个用于存储字符串长度,但即使使用2个字节的字符编码,仍然会留下16个字节。

1 个答案:

答案 0 :(得分:8)

在内部,V8对字符串有许多不同的表示形式:

  • SeqOneByteString:最简单的,包含一些标题字段,然后是字符串的字节(不是UTF-8编码,只能包含前256个unicode代码点中的字符)
  • SeqTwoByteString:相同,但每个字符使用两个字节(使用代理项对来表示不能用两个字节表示的unicode字符)。
  • SlicedString:其他字符串的子字符串。包含一个指向" parent"的指针。字符串和偏移量和长度。
  • ConsString:添加两个字符串的结果(如果超过一定大小)。包含指向两个字符串的指针(可能本身就是这些类型的字符串中的任何一种)。
  • ExternalString:用于从V8外部传入的字符串。

"内在化"只是一个标志,实际的字符串表示可以是上面的任何一个。

所有这些都有一个共同的父类String,其父级是Name,其父级是HeapObject(它是V8堆上分配的对象的V8类层次结构的根)。

  • HeapObject有一个字段:指向其Map的指针(这些是here的一个很好的解释)。
  • 名称会添加一个额外字段:哈希值。
  • String添加另一个字段:长度。

在32位系统上,每个都是4个字节。在64位系统上,每个系统都是8个字节。

如果您使用的是64位系统,那么SeqOneByteString的最小大小将为32字节:上述头字段为24字节,字符串数据至少为一个字节,向上舍入为多个8。

关于你的第二个问题,很难准确地说出发生了什么。可能是字符串使用的是2字节表示形式,并且其标题字段的大小超出了您的预期,或者可能是它的ConsString或SlicedString(其保留的大小将包含字符串)它指出)。

V8大部分时间都没有内部化字符串 - 它内化了在解析过程中找到的字符串常量和标识符名称,以及用作对象属性键的字符串,以及其他一些情况。