首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JavaScript: V8问题:小整数可重用吗?

JavaScript: V8问题:小整数可重用吗?
EN

Stack Overflow用户
提问于 2022-01-23 06:02:23
回答 2查看 136关注 0票数 0

根据V8博客中的这篇文章这个现存的问题,我们知道小整数通过指针标记直接编码到指针中。

Smi的“诀窍”是,它们不作为单独的对象存储:当您有一个引用smi的对象时,例如let foo = {smi: 42},则值42可以被smi编码并直接存储在"foo“对象中(而如果值为42.5,则该对象将存储指向单独的”HeapNumber“的指针)。但是,由于对象在堆上,所以Smi也是如此。

这意味着,如果我有两个具有相同对象值的不同对象,{smi: 42}。smi 42应该位于堆上的两个不同的内存位置,因为这两个对象都在堆上,值42直接编码到指针中,而不是有额外的存储。

但这与Chrome开发工具的内存分析结果相矛盾。考虑到这个片段

代码语言:javascript
复制
<body>
    <button id='btn'>btn</button>
    <script>  
    const btn = document.querySelector('#btn')
    function MyObject() {
        this.number = 3.14
        this.smi = 123
        this.undefined = undefined
        this.true = true
        this.false = false
        this.null = null
        this.string = 'foo'
    }
    let obj1
    let obj2
    btn.onclick = () => { 
        obj1 = new MyObject()
        obj2 = new MyObject()
    }
    </script>
</body>

我认为smi:123应该位于两个不同的位置,而double number = 3.14应该指向相同的number对象。

但事实并非如此-- smi位于相同的内存位置,而double则不是。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-01-23 16:49:03

对@JonasWilms的回答的另一个评论是:

如果您真的关心在幕后发生了什么,我建议您学习如何使用(本机,而不是DevTools)调试器并检查实际内存。DevTools是为了帮助你理解你的应用程序在做什么而设计的,虽然它与在引擎盖下发生的事情有很大的重叠,但这并不完全是一回事,而且很可能会有一些细节(比如Smis的显示方式)来显示这种差异。我认为堆快照使用raw_address → object ID映射,您看到的是将Smis放入这样一个映射中的自然结果。

对于测试用例的简化版本(只有function MyObject() { this.number = 12.5; this.smi = 23; }),您可以在内存中看到以下内容:

代码语言:javascript
复制
(gdb) x/5xw 0x1f010810aedc
0x1f010810aedc: 0x082c7db1  // pointer to map
                0x08002249  // pointer to properties (empty array)
                0x08002249  // pointer to elements (empty array)
                0x0810af71  // pointer to a HeapNumber
                0x0000002e  // Smi: 23 << 1 == 46 == 0x2e
(gdb) x/5xw 0x1f010810afa4
0x1f010810afa4: 0x082c7db1  // map (same as other object)
                0x08002249  // properties
                0x08002249  // elements
                0x0810afd9  // pointer to a HeapNumber
                0x0000002e  // Smi: 23 << 1

另一方面,HeapNumbers可以而且确实可以被重用。在这个例子中,我们没有看到这一点,因为还有另一种机制:对象属性使用可变的HeapNumbers。易变使得它们不可共享,在这个玩具示例中,整个方法只是浪费时间和内存;但对于典型的使用模式来说,这是一种有益的权衡,因为它允许更新值(特别是从优化的代码中更新),而无需每次分配新的HeapNumber。

如果您只是拥有一个function f() { return 12.5; },那么每次调用它时,它实际上都会返回相同的重用HeapNumber。

票数 3
EN

Stack Overflow用户

发布于 2022-01-23 11:25:38

smi 42应该位于堆上的两个不同的内存位置,因为这两个对象都在堆上,并且值42被直接编码到指针中,而不是具有额外的存储。

是。SMI存储两次,每次在每个对象值中存储一次。所以不,它们不被重用,实际上也不可能,因为它们是原始的值而不是可引用的东西。

dev工具并不显示指针驻留在内存中的位置,而是它指向的位置,在SMI情况下,这是一个无意义的位置,因为它实际上对值进行了编码。因此,由于两者编码相同的值,它们的“指向任何东西的指针”是相同的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70819548

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档