Web Worker 消耗大量内存

Web Worker consumes massive amount of memory

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

问题是在比较期间浏览器的主线程被阻塞导致无响应UI。比较函数的执行时间大约需要 10 毫秒,并且每 250 毫秒或 500 毫秒进行一次比较。

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

我以为我留下了一些引用,垃圾收集器无法释放内存。然而,一段时间后(一整天将我的应用程序剥离并尝试 deletenullundefined variables/data)我在下面创建了 fiddle我发送了 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 次重复终止 worker 并创建新的 worker 就会更快地释放内存。但它仍然不是一个解决方案,只是一个古玩。

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

基于此,我会说不存在挂起引用,但通过传输接收对象可能不会像新分配请求那样强制执行 gc 检查。

通过响应将对象传回似乎可以解决问题:

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

作为替代方案,确保 Worker 是重要的并且需要进行正常分配似乎也可以正确触发 gc,即:

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