7

我有一个应用程序在单击按钮后调用网络工作者。计算被移到工作人员以减轻 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(工人):

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

    // calculations...
    
    postMessage(output);
    close();
};

有没有办法避免在这个地方发生这些垃圾收集器事件?

UPD:在我看来,垃圾收集器事件的时间取决于发送给工作人员的数据量。
UPD2:关闭和启动垃圾收集器事件后仅发生两次,因此阻塞 UI 不到一秒钟。嗯?

4

1 回答 1

4

使用 Web Worker 时要记住的一件事,尤其是当您在示例中使用它们时,当您将对象发送给 worker 时,您正在克隆该对象。因此,让我们用一个愚蠢的例子来解决这个问题:

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

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

于 2013-10-01T05:41:29.563 回答