Web Worker消耗大量内存

时间:2016-01-25 22:30:31

标签: javascript multithreading google-chrome firefox web-worker

我正在尝试提高我的应用程序中的性能,该应用程序比较两个大画布的内容。

问题是在比较浏览器的主线程时阻止了什么导致无响应的UI。比较功能的执行时间约为10ms,每250ms或500ms进行一次比较。

为了解决这个问题,我提出了通过创建web worker来使用另一个线程的想法。它现在非常好用,但我意识到它消耗了大量的内存(在FF和Chrome中高达600MB - 在Edge中高达70MB,在所有浏览器中单线程版本从未达到100MB)。

我以为我留下了一些引用而垃圾收集器无法释放内存。但是,过了一段时间(整天将我的应用程序剥离成片并尝试deletenullundefined变量/数据)我在下面创建了小提琴,其中我发送的是1MB ArrayBuffer(即使我通过转移传递它)但没有任何处理,因为你可以看到它也消耗了大量的内存。

我有什么想法可以解决这个问题(任何替代解决方案或任何可能的工人改进)以及问题出在哪里?

var sortFilterDataWorker = function () {
    onmessage = function image2compare(ev) {
      postMessage('hi');
    };
}.toString();

/* PREPARE WORKER AS STRING TO CREATE JS BLOB FILE */
sortFilterDataWorker = sortFilterDataWorker.slice(sortFilterDataWorker.indexOf('{') + 1, -1).trim();

var blob = new Blob([sortFilterDataWorker]) // create blob file with worker code
  , blobUrl = window.URL.createObjectURL(blob) // create pseudo url to blob file
  , compareWorker = new Worker(blobUrl) 
  ;

setInterval(function(){
  var oneMB = new ArrayBuffer(8388608);
  compareWorker.postMessage(oneMB, [oneMB]); // transpile ArrayBuffer
}, 250);

FIDDLE

修改

我发现如果我每隔n次重复终止工作并创建新的就会更快释放内存。但它仍然不是一个古玩的解决方案。

1 个答案:

答案 0 :(得分:10)

我发现如果我从开发人员工具手动运行垃圾收集器 - >时间线清除了所有内存。同样,如果我从控制台开始与Worker上下文交互,则调用函数似乎会随机触发成功的gc。

基于此,我会说没有挂起引用,但通过传输接收对象可能不会强制执行gc检查,因为新的分配请求会。

使用响应传回对象似乎可以解决问题:

postMessage('hi', [ev.data]);  // process usage stays around 50MB

作为替代方案,确保工人是非平凡的并且需要进行正常分配似乎也恰当地触发了gc,即:

  postMessage('hi');
  var twoMB = new ArrayBuffer(8388608); // usage cycles 70MB - ~220MB