我正在尝试计算 v8 中字符串的内存使用量,并且我知道单个字符将占用 2 个字节。但是当我在开发工具中检查浅层大小和保留大小时,我对结果感到困惑:
function Student() {
this.name = 'lll';
}
var a = new Student();
var b = new String("ccccc");
浅层大小和保留大小都是 16 字节。为什么?
正如我想象的那样,浅层大小和保留大小将相等,并且该值将是 6 个字节。如果我将字符串从“lll”更改为“llll”,该值将增加 2 个字节。但它保持不变,如下所示:
有人可以向我解释一下吗?
(V8 开发人员在此。)
前面的一般说明:字符串在网络上非常常见,因此 JavaScript 引擎竭尽全力为您可以使用字符串执行的许多不同操作实现许多不同的优化,因此,现代 JS 引擎中的字符串处理系统倾向于变得非常复杂。排除了这一点,我们可以在这里专注于“简单”字符串。
单个字符需要 2 个字节
还有更多内容:V8 在内部区分一字节和两字节字符串。当给定字符串中的所有字符都可以用一个字节表示时,那么(通常)V8 就会这么做。
浅层大小和保留大小都是 16 字节。为什么?
评论者已经发布了一个描述“浅”和“保留”大小之间差异的链接,所以我不会深入讨论。对于简单的字符串来说,它确实总是相同的值。
堆上的所有对象都以一个形状描述符开始,该描述符占用一个指针大小(由于 64 位平台上的“指针压缩”,现在通常为 4 个字节)。
字符串在其对象头中另外还有两个 4 字节的字段:字符串的哈希值(经常需要它,因此为了避免一直重新计算它,它被缓存在那里)和字符串的长度。
之后,他们存储实际的字符。任何堆对象的大小必须是指针大小的倍数,即 4 的倍数,因此字符串的大小将向上舍入;最后几个字节可能未使用。
所以,总而言之,一个简单字符串的大小n
ASCII 字符为:
12 + 4 * Math.ceil(n/4)
(这可能会随着时间的推移而改变,如果在构建时关闭指针压缩,情况会有所不同,当字符串中有两字节字符时,情况会有所不同,当字符串是“切片”时,情况会有所不同" 或 "cons" 字符串,当该字符串与 Blink 共享时,它会有所不同,而且我可能忘记了某些情况下它也会有所不同。)
如果你稍微扩展你的实验,你会看到:
""
占用 12 个字节
"1"
通过"1234"
占用16字节
"12345"
通过"12345678"
占用20字节
"123456789"
占用 24 个字节,依此类推。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)