2016-11-09 98 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在大部分时间内没有内部化字符串 - 它将字符串常量和在解析过程中找到的标识符名称以及用作对象属性键的字符串(可能还有其他一些情况)内化。