为什么遍历Set的值会分配并创建垃圾? [英] Why does iterating over a Set's values allocate and create garbage?

查看:55
本文介绍了为什么遍历Set的值会分配并创建垃圾?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

昨天我问了这个问题关于如何遍历 Map 而不进行分配的信息.v8开发人员回复了以下内容:

Yesterday I asked this question on how to iterate over a Map without allocating. A v8 developer replied with the following:

但是,如果您只想对值进行处理,则可以通过仅对值进行迭代来避免创建它:for(map.values()的v){...}不会分配任何short生命的对象.遍历map.keys()也是一样.

But if you're only interested in processing the values anyway, you can avoid it being created by iterating over just the values: for (let v of map.values()) {...} does not allocate any short-lived objects. The same is true for iterating over map.keys().

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

I'm trying to replicate this in a test but I'm having trouble. Here's a demo I made that reproduces the problem I'm having with a simple Set. Paste the following code in an empty HTML file in its script tags:

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内存列,则会看到内存随着时间的推移而缓慢增长.

If you open this HTML file and then hit Shift+Escape it should open the Chrome Task Manager. If you then look at the Javascript Memory column, you'll see the memory slowly growing over time.

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

However, if you comment the line setInterval(setIterate, 1); and uncomment the line setInterval(arrayIterate, 1); and refresh the page you'll see that the memory usage stays constant.

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

That is, iterating over a Set produces garbage build-up over-time while iterating over an array does not.

是否有任何方法可以迭代Set,而不会随着时间的推移而产生此垃圾堆积?我正在开发一个浏览器游戏,并在渲染循环中迭代许多 Sets Maps ,由于运行了GC,偶尔会出现帧峰值.

Is there any way to iterate a Set without producing this garbage build-up over time? I'm developing a browser game and iterating over many Sets and Maps in my render loop and getting occasional frame-spikes due to the GC running.

推荐答案

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

Why does iterating over a Set's values allocate and create garbage?

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

It doesn't. Doing a million calls to setIterate with --trace-gc (in d8 or node) shows zero activity. If the function allocated even a single byte per iteration (which it can't; the minimum allocation granularity is two pointers, i.e. 8 bytes), then the young generation would have filled up at least once in that time.

有没有办法迭代Set而不随着时间的推移而产生这种垃圾堆积?

Is there any way to iterate a Set without producing this garbage build-up over time?

绝对;例如您的操作方式.

Absolutely; for example how you're doing it.

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

why does the Task Manager show memory increasing over time?

我看不到这样做.我已按原样复制粘贴了您的代码段,并让其放置了几分钟."JavaScript内存"此选项卡的Chrome任务管理器列中的所有列都没有增加一千字节.(实际上,这仅证明该测试不是真正的压力测试:一旦 sum 超过 1<<<<< 30> code,它 就会开始疯狂分配>,但这不是因为集合或数组...)

I don't see it doing that. I've copy-pasted your snippet exactly as-is and let it sit for a couple of minutes; the "JavaScript memory" column of Chrome's task manager for that tab hasn't budged by a single kilobyte. (Which actually only proves that this test isn't really a stress test: it will start allocating like crazy once sum exceeds 1<<30, but that's not because of the set or the array...)

疯狂的猜测:也许您安装了一些扩展程序,可以将代码注入每个页面并引起分配?无论如何,它不是 Set s上的 for..of 循环.

Wild guess: maybe you have some extension installed that injects code into every page and causes allocations? At any rate, whatever it is, it's not the for..of-loops over Sets.

这篇关于为什么遍历Set的值会分配并创建垃圾?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆