我正在尝试提高我的应用程序的性能,该应用程序比较了两个大 Canvas 的内容。
问题是在比较期间浏览器的主线程被阻止导致 UI 无响应。比较功能的执行时间大约需要 10 毫秒,并且每 250 毫秒或 500 毫秒进行一次比较。
为了解决这个问题,我想出了通过创建 web worker
来使用另一个线程的想法。 .它现在工作得很好,但我意识到它消耗了大量的内存(在 FF 和 Chrome 中高达 600MB - 在 Edge 中高达 70MB,在所有浏览器的单线程版本中它从未达到 100MB)。
我以为我留下了一些引用,垃圾收集器无法释放内存。然而,经过一段时间(整天将我的应用程序剥离并尝试 delete
、null
或 undefined
变量/数据)我在下面创建了 fiddle ,我在其中发送了 1MB ArrayBuffer
(即使我通过传输通过了它)但没有任何处理,正如你所看到的,它也消耗了大量的内存。
有什么想法可以解决这个问题(任何替代解决方案或任何可能的 worker 改进)以及问题出在哪里?
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 上下文交互,调用函数似乎会随机触发成功的 gc。
基于此,我会说没有挂起的引用,但是通过传输接收对象可能不会像新的分配请求那样强制进行 gc 检查。
用响应传回对象似乎可以解决这个问题:
postMessage('hi', [ev.data]); // process usage stays around 50MB
作为替代方案,确保 Worker 不平凡并且需要进行正常分配似乎也可以正确触发 gc,即:
postMessage('hi');
var twoMB = new ArrayBuffer(8388608); // usage cycles 70MB - ~220MB
关于javascript - Web Worker 消耗大量内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35003676/