【发布时间】: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 而不会随着时间的推移产生这种垃圾堆积?我正在开发一个浏览器游戏,并在我的渲染循环中迭代了许多 Sets 和 Maps,并且由于 GC 运行而偶尔出现帧峰值。
【问题讨论】:
-
无法重现,Chrome 版本 92。
-
嗯,您确定您查看的是正确的列吗?确保您查看的是
Javascript memory列,而不是Memory footprint列。另外,您使用的是哪个操作系统?也许这有影响?我在 Windows 10 上。我使用的是我认为是最新的 Chrome 91?我什至尝试下载 Chrome 测试版,但仍然存在同样的问题。 -
我尝试使用 Chrome Dev 版本 (92),但它似乎仍然在那里发生。
-
哦,您正在使用任务管理器。我正在使用开发工具。如果您运行配置文件(让它运行一段时间),性能选项卡将显示堆增长,并且没有让人想起分配代码的锯齿。
-
这不是因为它每隔几秒钟就会收集一次垃圾,所以很难说吗?因为在这个例子中它是非常少的垃圾,所以很难分辨,因为差异是如此之小。
标签: javascript performance iterator set v8