【问题标题】:Understanding String heap size in Javascript / V8理解 Javascript/V8 中的字符串堆大小
【发布时间】:2016-11-09 17:06:50
【问题描述】:

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

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

1) 具有不同 @ 对象 ID 的相同 2 个字符串(即“dt”)的多个副本都指定为 OneByteStrings。 heapdump 说每个副本都有一个 32 字节的浅表和保留大小。目前尚不清楚一个两字节字符串如何保留 32 的大小以及为什么这些字符串似乎没有被保留。

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

【问题讨论】:

    标签: javascript string v8


    【解决方案1】:

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

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

    “Internalized”只是一个标志,实际的字符串表示可以是上述任何一种。

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

    • HeapObject 有一个字段:指向其 Map 的指针(对这些 here 有很好的解释)。
    • 名称添加了一个附加字段:哈希值。
    • 字符串添加了另一个字段:长度。

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

    如果您使用的是 64 位系统,则 SeqOneByteString 的最小大小为 32 个字节:上述标头字段为 24 个字节,加上字符串数据至少一个字节,四舍五入为 8 的倍数.

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

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

    【讨论】:

      猜你喜欢
      • 2017-12-05
      • 2012-01-15
      • 1970-01-01
      • 2012-05-27
      • 2011-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多