如果v8在对象增长时重新出现

时间:2018-04-24 22:45:39

标签: javascript hash v8

假设您对某个对象进行了更改,该对象触发了存储哈希值的基础数组或数据结构大小的更改。

var x = { a: 1, b: 2, c: 3 }
// trigger a resize theoretically
x.d = 4
x.e = 5
x.f = 6

假设哈希的底层数组在v8中看起来像这样。

[ 1, 3, 2, null, null ]

最初创造了一些额外的空间。但它还不够,所以它必须增长。有两种选择。

  1. 它会在当前的地方保留原始值。
  2. 它增长并且重新发送,将值移动到任意新的位置。
  3. 所以它看起来像:

    // (1) 1, 3, 2 stay where they are
    [ 1, 3, 2, 6, 4, 5, null, null, null, null ]
    
    // (2) 1, 3, 2 are moved
    [ 6, 2, 5, 3, 4, 1, null, null, null, null ]
    

    想知道v8在这种情况下做了什么。还想知道调整大小的启发式是什么(当它长大时它会使数组大小加倍等)。

2 个答案:

答案 0 :(得分:1)

V8引擎使用两个对象表示:

  • 字典模式 - 将对象存储为键 - 值映射为hash map
  • 快速模式 - 其中存储的对象类似structs,其中属性访问不涉及任何计算。

快速模式通常可以更快地进行属性访问 - 但需要知道对象的结构。

V8最初将尝试构建一个对象看起来像是"隐藏类"的模板。该对象将通过隐藏类进行转换,直到V8放弃并将对象存储为慢属性。

我会更深入地了解" How does Bluebird's util.toFastProperties function make an object's properties “fast”? "中的相关代码。

关于你的直接问题,对象将"fast assign"对这些属性赋值(在每个这样的赋值上)并迁移到不同的映射(根据需要复制内存)。

答案 1 :(得分:1)

V8已经发布了关于如何存储属性的详细blogpost

对于字典属性V8(在您的示例中不是这种情况),底层数据结构是hash map,因此底层数组中的实际位置会发生变化。

但是,JavaScript要求按插入顺序迭代属性。因此,每个字典当前都会跟踪它的插入位置,以便以正确的顺序迭代条目。

对于字典大小,V8保持使用2的幂,并尝试将它们保持大致50% empty以避免频繁的哈希冲突。