使用 Web Workers(垃圾收集器)可能出现内存泄漏
我有一个应用程序,它在单击按钮后调用网络工作人员。计算被转移到工作线程以减轻 UI 负担,并使其在计算时响应用户操作。
一切顺利,大约 0.8-1.5 秒后,工作人员发送响应。在 worker.onmessage
中,我执行了所有需要的 DOM 操作,但在此垃圾收集器出现之后,实际上会阻塞 UI 2 秒或更长时间,具体取决于 CPU。这真的让我很困惑,因为 UI 阻塞正是我想要防止的。
这是时间线/内存控制台选项卡的屏幕截图:
如您所见,垃圾收集器事件在所有 DOM 操作之后发生。实际上只有一个重绘事件(使用了DocumentFragment
)。
主要js代码:
var sortWorker = new Worker('js/contactsorter.js');
sortWorker.onmessage = function(e) {
var messages = [];
e.data.forEach(function(userDoc) {
var contactSection = _drawContact(userDoc);
messages.push(contactSection);
});
meta.append(messages); // this actually appends document fragment as a child
};
sortWorker.postMessage(postMessageData);
contactsorter.js(worker):
onmessage = function(e) {
var uid, output = [], usersStat = {};
// calculations...
postMessage(output);
close();
};
有没有办法避免这个地方的这些垃圾收集器事件?
UPD:在我看来,垃圾收集器事件时间取决于发送给工作人员的数据量。
UPD2:关闭和启动后,垃圾收集器事件仅发生两次,因此阻塞 UI 的时间不到一秒。嗯?
I have an app which calls web worker after the button click. The calculations are moved to worker to relieve UI and make it responsive to user actions while calculations are being made.
Everything goes okay and after about 0.8-1.5s the worker sends a response. In worker.onmessage
I perform all the needed DOM actions, but after this Garbage Collector appears and practically blocks the UI for 2 or more seconds depending on CPU. This is really confusing me, because UI blocking is what I want to prevent.
Here's the screenshot of timeline/memory console tab:
As you can see Garbage Collector events happen just after all DOM manipulations. Actually there's only one repaint event (DocumentFragment
is used).
Main js code:
var sortWorker = new Worker('js/contactsorter.js');
sortWorker.onmessage = function(e) {
var messages = [];
e.data.forEach(function(userDoc) {
var contactSection = _drawContact(userDoc);
messages.push(contactSection);
});
meta.append(messages); // this actually appends document fragment as a child
};
sortWorker.postMessage(postMessageData);
contactsorter.js (worker):
onmessage = function(e) {
var uid, output = [], usersStat = {};
// calculations...
postMessage(output);
close();
};
Is there any way to avoid these Garbage Collector events in this place or not?
UPD: it seems to me that Garbage Collector event(s) time depends on data amount that was sent to worker.
UPD2: After shutdown and boot Garbage Collector events happen only twice thus blocking UI for less than a second. Hm?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
对于 Web Workers 需要记住的一件事是,当您将对象发送给工作人员时,您正在克隆该对象,尤其是当您在示例中使用它们时。因此,让我们用一个愚蠢的例子来运行一下:
既然你说这是一个 chrome 应用程序(另一条评论),那么也许你可以重组你的代码以利用 可传输对象避免克隆创建临时对象当然,要使用可传输对象,您必须将其重组为数组缓冲区,这本身就是一个黑暗魔法。
One thing to remember with Web Workers, and especially as you have them used in your example, is that you are cloning the object when you send it over to the worker. So lets run through this with a silly example:
Since you said that this was a chrome app (another comment), then maybe you can restructure your code to make use of Transferable Objects to avoid the object Cloning creation of temporary objects etc. Course, to use transferable objects you'd have to restructure as an array buffer and that's a dark magic all of itself.