Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/470.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用Web Worker(垃圾收集器)可能存在内存泄漏_Javascript_Html_Javascript Events_Garbage Collection_Web Worker - Fatal编程技术网

Javascript 使用Web Worker(垃圾收集器)可能存在内存泄漏

Javascript 使用Web Worker(垃圾收集器)可能存在内存泄漏,javascript,html,javascript-events,garbage-collection,web-worker,Javascript,Html,Javascript Events,Garbage Collection,Web Worker,我有一个在点击按钮后调用web worker的应用程序。计算将移动到worker,以释放UI,并使其在进行计算时响应用户操作 一切正常,大约0.8-1.5秒后,工人发送响应。在worker.onmessage中,我执行所有需要的DOM操作。但在此GC出现后,实际上会根据CPU将UI阻塞2秒或更长时间。这让我很困惑,因为UI阻塞是我想要阻止的 以下是时间线/内存控制台选项卡的屏幕截图: 正如您所看到的,GC事件发生在所有DOM操作之后。实际上只有一个重绘事件(使用DocumentFragment)

我有一个在点击按钮后调用web worker的应用程序。计算将移动到worker,以释放UI,并使其在进行计算时响应用户操作

一切正常,大约0.8-1.5秒后,工人发送响应。在worker.onmessage中,我执行所有需要的DOM操作。但在此GC出现后,实际上会根据CPU将UI阻塞2秒或更长时间。这让我很困惑,因为UI阻塞是我想要阻止的

以下是时间线/内存控制台选项卡的屏幕截图:

正如您所看到的,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);
contactsorter.js(工人):

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

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

对于Web Workers,尤其是在您的示例中使用它们时,需要记住的一点是,当您将对象发送给worker时,您正在克隆该对象。让我们用一个愚蠢的例子来说明这一点:

  • 制作大对象(你在评论中说了2M…wtf…哇)-在主线程中分配2M
  • Post to worker,主线程中仍有2M,加上主线程中创建为fluff的任何额外内容,用于JSONify对象/数组,然后发送到worker,其中worker中有2M
  • 猛击那个该死的工人。。。在这里,主线程中的2M+只是坐在那里等待GC,现在可能会发生,可能不会。。。GC在一定数量的新一代对象达到阈值后触发。。。比如说在创建大量新对象和dom元素之后或期间:D
  • Worker用一条消息回应,让我们假设现在在主线程中为新的2M(耶)重新创建2M,再加上反JSONify对象所需的任何绒毛内存对象。。。你知道这是怎么回事

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

    对象有多大?有多少我们在谈论什么样的数字?您正在创建哪些DOM节点?GC事件是否与已排序的联系人数成线性比例?JSON.stringify说大约有2M。这些对象的子对象是对象。在worker响应(它输出一个数组)之后,我创建DocumentFragment并向其添加大约400个“div”元素。之后,我将片段附加到DOM中。关于最后一个问题,我需要重写代码来进行测试,所以稍后我会对此进行评论。顺便说一句:新升级了最后一个问题:不,GC事件不会根据数据量进行缩放。此外,我甚至在时间线上都找不到它,尽管在这段时间里,用户界面正在计时。奇怪。对其他支持网络工作者的浏览器有什么影响?是否值得删除浏览器安装并重试?作为记录,我自己也尝试过一些繁重的工作和DOM操作,但没有重新创建您的图形-尽管我确实会遇到暂停和GCs。您可能会受益于在firefox中使用大约:内存。。。它不仅可以让您确切地看到内存是如何分配的,还可以让您触发GC。(点击页面底部的GC按钮。)Firefox的最新版本(beta/每夜版)会有更好的分析,尽管这对你来说可能根本不重要。“你在评论中说了2M…wtf…wow”-对于图形、音频或分析软件等应用程序来说,通常要大得多。我在这里传递的是12GB(!)的阵列,使用可传输的阵列没有问题。@JohnWeisz-同意,最近我还经常使用WebAudio等更大的对象。但在2013年末的机器上,这似乎很多。我认为他的实际问题更多地与创建临时对象的负载有关,并且作为循环或映射器的一部分。。。更不用说不知道他在教堂里干什么了。
    onmessage = function(e) {
        var uid, output = [], usersStat = {};
    
        // calculations...
    
        postMessage(output);
        close();
    };