v8存储一个字符串需要多少内存?

4

我正在尝试计算v8中字符串的内存使用量,我知道一个单独字符需要2个字节。但是当我在开发工具中检查浅层大小和保留大小时,结果让我感到困惑:

function Student() {
    this.name = 'lll';
}

var a = new Student();

var b = new String("ccccc");

enter image description here

浅大小和保留大小都是16字节。为什么?
我想象中,浅大小和保留大小应该相等,值为6个字节。如果我将字符串从“lll”更改为“llll”,则值将增加2个字节。但实际上它仍然是以下内容:

enter image description here

有人可以向我解释一下吗?


也许这篇文章可以帮助您:https://www.yourkit.com/docs/java/help/sizes.jsp - Dpk
@Dpk ... Java 不是 JavaScript。 - Bravo
做一些更多的测试,使用更长的字符串,也许一个字符串总是存储在16字节的倍数中。 - Bravo
@Bravo,我知道,我只是想帮助理解“浅大小”和“保留大小”的术语。 - Dpk
1
https://dev59.com/kFIG5IYBdhLWcg3w9W3d - Dpk
显示剩余2条评论
1个回答

16

(我是一名V8开发者。)
总体而言:字符串在Web上非常常见,因此JavaScript引擎会为许多不同的字符串操作实现许多不同的优化,因此现代JS引擎中的字符串处理系统往往非常复杂。不过,在这方面我们可以专注于“简单”的字符串。

一个单独字符将占用2个字节。

事实上还有更多内容:V8内部区分单字节和双字节字符串。当给定字符串中的所有字符都可以用一个字节来表示时,V8通常会采用这种形式。

浅大小和保留大小都是16个字节。为什么?

评论者已经发布了有关“浅层大小”和“保留大小”之间差异的描述链接,所以我不会涉及到那点。对于简单的字符串,它们的大小永远是相同的。

堆上的所有对象都以形状描述符开始,该描述符占用一个指针大小(这些天通常为4个字节,由于在64位平台上的“指针压缩”)。

字符串还在其对象头中额外存储了两个4个字节的字段:字符串的哈希值(经常需要使用,因此为避免每次都要重新计算,它被缓存在那里),以及字符串的长度。

此后,它们会存储实际字符。任何堆对象的大小必须是指针大小的倍数,即4的倍数,因此字符串的大小将向上舍入;最后几个字节可能未被使用。

因此,简单ASCII字符数为n的字符串的大小为:

12 + 4 * Math.ceil(n/4)

这可能会随时间而改变,如果在构建时关闭了指针压缩,则会有所不同;如果字符串中有双字节字符,则会有所不同;如果字符串是“切片”或“cons”字符串,则会有所不同;如果字符串与Blink共享,则会有所不同。我可能还忘记了一些其他情况,也会导致结果不同。

如果你稍微扩展一下你的实验,你会发现:
"" 占用 12 字节
"1""1234" 占用 16 字节
"12345""12345678" 占用 20 字节
"123456789" 占用 24 字节,依此类推。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接