I am trying to improve performance in my app which pares content of two large canvases.
The problem is that during parison main thread of the browser is blocked what results unresponsive UI. Execution time of parison function takes approx 10ms and parison happens every 250ms or 500ms.
To solve that problem I came up with idea of use another thread by creating a web worker
. It works pretty nice right now, but I realized that it consumes insane amount of memory (up to 600MB in FF and Chrome - in Edge it's up to 70MB, it never reached 100MB in single thread version on all browsers).
I thought that I left some references and Garbage Collector can't release memory. However, after some time (whole day of stripping my app to the pieces and trying to delete
, null
or undefined
variables/data) I created fiddle below in which I'm sending 1MB ArrayBuffer
(even though I passed it by transferring) but without any processing and as you can see it consumes massive amount of memory too.
Any ideas how I can solve that problem (any alternative solutions or any possible worker improvements) and where the problem is?
var sortFilterDataWorker = function () {
onmessage = function image2pare(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
, pareWorker = new Worker(blobUrl)
;
setInterval(function(){
var oneMB = new ArrayBuffer(8388608);
pareWorker.postMessage(oneMB, [oneMB]); // transpile ArrayBuffer
}, 250);
FIDDLE
EDIT:
I found out that if I terminate worker every n repeats and create new one releases memory faster. But it's still not a solution just a curio.
I am trying to improve performance in my app which pares content of two large canvases.
The problem is that during parison main thread of the browser is blocked what results unresponsive UI. Execution time of parison function takes approx 10ms and parison happens every 250ms or 500ms.
To solve that problem I came up with idea of use another thread by creating a web worker
. It works pretty nice right now, but I realized that it consumes insane amount of memory (up to 600MB in FF and Chrome - in Edge it's up to 70MB, it never reached 100MB in single thread version on all browsers).
I thought that I left some references and Garbage Collector can't release memory. However, after some time (whole day of stripping my app to the pieces and trying to delete
, null
or undefined
variables/data) I created fiddle below in which I'm sending 1MB ArrayBuffer
(even though I passed it by transferring) but without any processing and as you can see it consumes massive amount of memory too.
Any ideas how I can solve that problem (any alternative solutions or any possible worker improvements) and where the problem is?
var sortFilterDataWorker = function () {
onmessage = function image2pare(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
, pareWorker = new Worker(blobUrl)
;
setInterval(function(){
var oneMB = new ArrayBuffer(8388608);
pareWorker.postMessage(oneMB, [oneMB]); // transpile ArrayBuffer
}, 250);
FIDDLE
EDIT:
I found out that if I terminate worker every n repeats and create new one releases memory faster. But it's still not a solution just a curio.
Share Improve this question edited Jan 27, 2016 at 9:00 LJ Wadowski asked Jan 25, 2016 at 22:30 LJ WadowskiLJ Wadowski 6,72011 gold badges47 silver badges77 bronze badges1 Answer
Reset to default 13 +50I found that if I run the garbage collector manually from developer tools -> Timeline it clears out all of the memory. Similarly, if I begin interacting with the Worker context from the console, calling functions seems to randomly trigger successful gc.
Based on this, I would say that there is not a hanging reference, but that receiving objects via a transfer may not force a gc check as new allocation requests would.
Transferring the object back with a response seems to workaround the problem:
postMessage('hi', [ev.data]); // process usage stays around 50MB
As an alternative, making sure the Worker is non-trivial and will need to do normal allocations also seems to properly trigger gc, i.e:
postMessage('hi');
var twoMB = new ArrayBuffer(8388608); // usage cycles 70MB - ~220MB