使用Web Workers(垃圾收集器)可能发生内存泄漏

Dmi*_*rin 8 javascript html5 garbage-collection javascript-events web-worker

我有一个应用程序,在按钮单击后调用web worker.计算将移至工作人员以缓解UI并使其在进行计算时响应用户操作.

一切顺利,大约0.8-1.5秒之后工人发出回应.在worker.onmessage中,我执行所有需要的DOM操作.但是在此GC出现之后,根据CPU的不同,实际上会阻止UI 2秒或更长时间.这真让我感到困惑,因为UI阻塞是我想要阻止的.

以下是时间轴/内存控制台选项卡的屏幕截图:http://i.imgur.com/zUoHa.jpg

正如您所看到的,GC事件恰好在所有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);
Run Code Online (Sandbox Code Playgroud)

contactsorter.js(worker):

onmessage = function(e) {
    var uid, output = [], usersStat = {};

    // calculations...

    postMessage(output);
    close();
};
Run Code Online (Sandbox Code Playgroud)

有没有办法在这个地方避免这些GC事件?

UPD:在我看来,GC事件的时间取决于发送给工人的数据量.UPD2:关闭和启动后GC事件只发生两次,从而阻止UI不到一秒钟.嗯?

小智 5

对于 Web Workers 需要记住的一件事是,当您将对象发送给工作人员时,您正在克隆该对象,尤其是当您在示例中使用它们时。让我们用一个愚蠢的例子来解释一下:

  1. 制作大对象(你在评论中说 2M...wtf...哇) - 在主线程中分配 2M
  2. 发布到工作人员,主线程中仍然有 2M,加上主线程中作为绒毛创建的任何额外内容以 JSON 化您的对象/数组,然后发送到工作人员,工作人员中的 2M 是的
  3. 突突工作人员中的那个傻瓜...这里主线程中的 2M+ 只是坐在等待 GC,现在可能发生,可能不会...GC 在一定数量的新生代对象达到阈值后触发...就像比如说在创建大量新对象和 dom 元素之后或期间:D
  4. Worker 回复一条消息,假设 2M 现在在主线程中重新生成了一个新的 2M(是的),再加上 de JSONify 对象所需的任何绒毛内存对象......你知道这是怎么回事。

既然你说这是一个 chrome 应用程序(另一条评论),那么也许你可以重组你的代码以利用可转移对象来避免对象克隆创建临时对象等。当然,要使用可转移对象,你必须重组作为数组缓冲区,这本身就是一个黑暗魔法。