【问题标题】:Why does iterating over a Set's values allocate and create garbage?为什么迭代 Set 的值会分配和创建垃圾?
【发布时间】:2021-08-05 01:17:32
【问题描述】:

昨天我问this question 如何在不分配的情况下迭代Map。一位 v8 开发人员回复如下:

但是,如果您只对处理值感兴趣,则可以通过仅迭代值来避免创建它: for (let v of map.values()) {...} 不会分配任何短- 有生命的物体。遍历 map.keys() 也是如此。

我正在尝试在测试中复制它,但我遇到了麻烦。这是我制作的一个演示,它重现了我在使用简单的Set 时遇到的问题。将以下代码粘贴到其脚本标签中的空 HTML 文件中:

let a = new Set([ 1, 2, 3, 4, 5 ]);
let b = [ 1, 2, 3, 4, 5 ];

let sum = 0;

function setIterate() {
  for (let item of a.values()) {
    sum += item;
  }
}

function arrayIterate() {
  for (let i = 0; i < b.length; i++) {
    sum += b[i];
  }
}

setInterval(setIterate, 1);
// setInterval(arrayIterate, 1);

如果您打开此 HTML 文件,然后点击Shift+Escape,它应该会打开 Chrome 任务管理器。如果您随后查看Javascript Memory 列,您会看到内存随着时间的推移而缓慢增长。

但是,如果您注释setInterval(setIterate, 1); 行并取消注释setInterval(arrayIterate, 1); 行并刷新页面,您会看到内存使用量保持不变。

也就是说,迭代 Set 会随着时间的推移产生垃圾堆积,而迭代数组则不会。

有没有什么方法可以迭代 Set 而不会随着时间的推移产生这种垃圾堆积?我正在开发一个浏览器游戏,并在我的渲染循环中迭代了许多 SetsMaps,并且由于 GC 运行而偶尔出现帧峰值。

【问题讨论】:

  • 无法重现,Chrome 版本 92。
  • 嗯,您确定您查看的是正确的列吗?确保您查看的是 Javascript memory 列,而不是 Memory footprint 列。另外,您使用的是哪个操作系统?也许这有影响?我在 Windows 10 上。我使用的是我认为是最新的 Chrome 91?我什至尝试下载 Chrome 测试版,但仍然存在同样的问题。
  • 我尝试使用 Chrome Dev 版本 (92),但它似乎仍然在那里发生。
  • 哦,您正在使用任务管理器。我正在使用开发工具。如果您运行配置文件(让它运行一段时间),性能选项卡将显示堆增长,并且没有让人想起分配代码的锯齿。
  • 这不是因为它每隔几秒钟就会收集一次垃圾,所以很难说吗?因为在这个例子中它是非常少的垃圾,所以很难分辨,因为差异是如此之小。

标签: javascript performance iterator set v8


【解决方案1】:

为什么迭代 Set 的值会分配和创建垃圾?

它没有。使用--trace-gc(在d8node 中)对setIterate 进行一百万次调用显示零活动。 如果函数在每次迭代时甚至分配了一个字节(它不能;最小分配粒度是两个指针,即 8 个字节),那么年轻代至少会被填满一次时间。

有没有什么方法可以迭代 Set 而不会随着时间的推移产生这种垃圾堆积?

绝对;例如你是怎么做的。

为什么任务管理器显示内存随时间增加?

我不认为它会这样做。我已经照原样复制粘贴了你的 sn-p 并让它静置几分钟;该选项卡的 Chrome 任务管理器的“JavaScript 内存”列没有变化一千字节。 (这实际上只是证明这个测试并不是真正的压力测试:一旦sum 超过1&lt;&lt;30,它开始疯狂分配,但这不是因为集合或数组.. .)


大胆猜测:也许您安装了一些扩展程序,将代码注入每个页面并导致分配?无论如何,不​​管它是什么,它都不是for..of-loops over Sets。

【讨论】:

  • 我不认为这是任何扩展,因为我没有运行其他程序,没有打开其他选项卡,也没有启用任何扩展。我想也许这只是 Chrome 的一个错误?我注意到它只在我刷新页面时发生。也就是说,如果我重新启动 Chrome 然后打开页面,则没有分配,但是如果我然后硬刷新页面然后在任务管理器中查看,那么它会显示分配随着时间的推移而增长。嗯..无论如何,我相信你它没有分配。
猜你喜欢
  • 2020-12-17
  • 1970-01-01
  • 2013-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多