Javascript Web Worker消耗大量内存
我正在努力提高我的应用程序的性能,它比较了两张大画布的内容 问题在于,在比较期间,浏览器的主线程被阻塞,导致UI无响应。比较功能的执行时间约为10ms,每250ms或500ms进行一次比较 为了解决这个问题,我想出了通过创建Javascript Web Worker消耗大量内存,javascript,multithreading,google-chrome,firefox,web-worker,Javascript,Multithreading,Google Chrome,Firefox,Web Worker,我正在努力提高我的应用程序的性能,它比较了两张大画布的内容 问题在于,在比较期间,浏览器的主线程被阻塞,导致UI无响应。比较功能的执行时间约为10ms,每250ms或500ms进行一次比较 为了解决这个问题,我想出了通过创建webworker来使用另一个线程的想法。它现在运行得很好,但我意识到它消耗了惊人的内存(FF和Chrome的内存高达600MB,Edge的内存高达70MB,在所有浏览器上的单线程版本中从来没有达到100MB) 我想我留下了一些引用,垃圾收集器无法释放内存。然而,经过一段时间
webworker
来使用另一个线程的想法。它现在运行得很好,但我意识到它消耗了惊人的内存(FF和Chrome的内存高达600MB,Edge的内存高达70MB,在所有浏览器上的单线程版本中从来没有达到100MB)
我想我留下了一些引用,垃圾收集器无法释放内存。然而,经过一段时间(整天把我的应用剥离成碎片,并试图删除,null
或未定义的变量/数据),我创建了下面的fiddle,我在其中发送1MB阵列缓冲
(即使我通过传输传递了它)但是没有任何处理,正如你所看到的,它也消耗了大量的内存
有什么想法可以解决这个问题(任何替代解决方案或任何可能的工人改进)以及问题在哪里
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次重复终止一个worker并创建一个新的worker,那么释放内存的速度会更快。但它仍然不是一个解决方案,只是一个古董。我发现,如果我从developer tools->Timeline手动运行垃圾收集器,它会清除所有内存。类似地,如果我从控制台开始与工作上下文交互,调用函数似乎会随机触发成功的gc
基于此,我认为不存在挂起引用,但通过传输接收对象可能不会像新的分配请求那样强制执行gc检查
通过响应将对象传输回来似乎可以解决问题:
postMessage('hi', [ev.data]); // process usage stays around 50MB
另一种选择是,确保工作人员不琐碎且需要进行正常分配似乎也能正确触发gc,即:
postMessage('hi');
var twoMB = new ArrayBuffer(8388608); // usage cycles 70MB - ~220MB
谢谢@Etsitra,您的最小化测试用例非常完美。您还应该将bug直接提交到chromium.org和bugzilla,这样环境最终就可以满足您的需要,而无需采取变通措施。我上周确实报告了这一点,所以我希望他们能够修复它。不管怎样,在我实现了你的修复应用程序之后,它的性能终于达到了我的预期,再次感谢你!虽然这一修正有点帮助,但它并没有解决我的漏洞。gc经常运行并清除所有内存,但在这之后,内存消耗会更快,在两次gc运行之间达到越来越高的值。我有点不知所措…@Fuzzyma我的例子在加压和观察gc方面比试图优化它更好。尝试从用1字节数组分配替换引用开始的不太激烈的方法可能会有效地触发它,同时保留更少的资源。