我正在尝试提高我的应用程序中的性能,该应用程序比较两个大画布的内容。
问题是在比较浏览器的主线程时阻止了什么导致无响应的UI。比较功能的执行时间约为10ms,每250ms或500ms进行一次比较。
为了解决这个问题,我提出了通过创建web worker
来使用另一个线程的想法。它现在非常好用,但我意识到它消耗了大量的内存(在FF和Chrome中高达600MB - 在Edge中高达70MB,在所有浏览器中单线程版本从未达到100MB)。
我以为我留下了一些引用而垃圾收集器无法释放内存。但是,过了一段时间(整天将我的应用程序剥离成片并尝试delete
,null
或undefined
变量/数据)我在下面创建了小提琴,其中我发送的是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);
修改
我发现如果我每隔n次重复终止工作并创建新的就会更快释放内存。但它仍然不是一个古玩的解决方案。
答案 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