【问题标题】:Why do empty objects take more memory than non-empty ones?为什么空对象比非空对象占用更多内存?
【发布时间】:2020-03-21 11:27:07
【问题描述】:

我发现 V8 对象有相当多的内存开销:我有一个大部分是空对象的数组;每个元素需要高达 64 个字节。 (相比之下,Java 需要 16 个字节。)

$ node --expose-gc  -e '
  gc();
  const start = process.memoryUsage().heapUsed;
  var a = Array(50 * 1000);
  for (let i = 0; i < a.length; i++) a[i] = {};
  gc();
  console.log(process.memoryUsage().heapUsed - start)
'
3231304

然后我发现我可以通过向我的对象添加一个虚拟属性来减少 37% 的内存使用量。

$ node --expose-gc  -e '
    gc();
    const start = process.memoryUsage().heapUsed;
    var a = Array(50 * 1000);
    for (let i = 0; i < a.length; i++) a[i] = {lifeTheUniverseAndEverything:42};
    gc(); 
    console.log(process.memoryUsage().heapUsed - start)
'
2028440

为什么向我的对象添加属性会减少我的内存使用量?

$ node -v
v12.7.0

$ uname -a
Linux paul 4.15.0-70-generic #79-Ubuntu SMP Tue Nov 12 10:36:11 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

【问题讨论】:

  • 在带有节点 v8.12.0 的 macOS 10.14 上验证。更奇怪的是:如果我们在循环中执行 { var c = "xxxx" + i + "xxxx"; a[i] = {c:42}; },它需要 2271136 字节 - 但如果我们执行 { var c = "xxxx" + i + "xxxx"; a[i] = {c:c}; } 突然它需要 5860328 字节!我最初认为这可能与 V8 的对象形状优化有关,但这些结果让我质疑......
  • @nneonneo 第二个结果并不令人惊讶,因为您存储了许多(不同的)~15 个字符的字符串。 100k 元素额外 30 字节...额外 3MB。
  • 这很有趣,因为这两种情况下的 keys 都是必须存储的大字符串 - 但它们不会对大小产生可衡量的影响。跨度>
  • @nneonneo,我想你的意思是写{[c]:42}作为第一个例子,而不是{c:42}。
  • 哦,我的错。我的 JS 明显生锈了 - 是的,我想要 [c]:42。这使得结果更符合预期,所以现在我确信我有正确的答案(如下)。

标签: node.js optimization memory v8 jit


【解决方案1】:

Node (V8) 做出以下假设:如果您的对象为空{},那么它可能会添加属性。因此,它为对象本身的四个属性分配了足够的空间。

另一方面,如果对象字面量已经有属性,那么它就不会分配任何额外的空间来节省内存。

这就是您看到空对象占用约 64 个字节的原因。

部分信息来自阅读 V8 博客文章,以及来自 Matt Zeunert 的内容丰富的细分:https://www.mattzeunert.com/2017/03/29/v8-object-size.html

【讨论】:

  • 这里是 V8 开发者。我可以确认这一点:使用{} 创建的空对象为未来的属性预先分配了一些空间。现代 JavaScript 引擎经过优化,可以在实际代码上表现良好,这通常会产生在减少的测试/微基准测试中看起来“怪异”的副作用。
  • @jmrk,我会为自己辩护说这是创建通常为空对象的真实代码 :) 但是是的,我知道这通常是正确的做法。
  • 这不是图数据结构的问题吗?空集通常用作 Null 对象,以避免在每次访问时检查未定义,并且空叶节点很容易代表树中对象数的一半。
  • 叶节点通常会附加一些数据(例如节点标签),因此对象不会为空。不存在的叶子通常会在父级中表示为 null。
猜你喜欢
  • 2023-01-03
  • 2019-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-25
  • 2023-03-07
  • 2022-08-05
  • 1970-01-01
相关资源
最近更新 更多