开发者

Possible memory leaks using Web Workers (Garbage Collector)

开发者 https://www.devze.com 2023-04-05 10:17 出处:网络
I have an app which calls web worker after the button click. The calculations are moved to worker to relieve UI and make it responsive to user actions while calculations are being made.

I have an app which calls web worker after the button click. The calculations are moved to worker to relieve UI and make it responsive to user actions while calculations are being made.

Everything goes okay and after about 0.8-1.5s the worker sends a response. In worker.onmessage I perform all the needed DOM actions, but after this Garbage Collector appears and practically blocks the UI for 2 or more seconds depending on CPU. This is really confusing me, because UI blocking is what I want to prevent.

Here's the screenshot of timeline/memory console tab:

Possible memory leaks using Web Workers (Garbage Collector)

As you can see Garbage Collector events happen just after all DOM manipulations. Actually there's only one repaint event (DocumentFragment is used).

Main js code:

var sortWorker = new Worker('js/contactsorter.js');
sortWorker.onmessage = function(e) {
    var messages = [];
    e.data.forEach(function(userDoc) {
        var contactSection = _drawContact(userDoc);
        messages.push(contactSection);
    });
    
    meta.append(messages); // this actually appends document fragment as a child
};

sortWorker.postMessage(postMessageData);

contactsorter.js (worker):

onmessage = function(e) {
    var uid, output = [], usersStat = {};

    // calculations...
    
    postMessage(output);
    close();
};

Is there any way to avoid these Garbage Collector events in this place or not?

UPD: it seems to me that Garbage C开发者_运维技巧ollector event(s) time depends on data amount that was sent to worker.

UPD2: After shutdown and boot Garbage Collector events happen only twice thus blocking UI for less than a second. Hm?


One thing to remember with Web Workers, and especially as you have them used in your example, is that you are cloning the object when you send it over to the worker. So lets run through this with a silly example:

  1. Make big object (you said 2M in a comment... wtf... wow) - 2M allocated in main thread
  2. Post to worker, 2M in main thread still, plus whatever extra was created as fluff in the main thread to JSONify your object/array, then off to worker where 2M in worker yay
  3. Chug on that sucker in worker... here the 2M+ in the main thread is just sitting around waiting to GC, might happen now, might not... the GC triggers after a certain amount of new generation objects hit threshold... like say after or during the creation of a ton of new objects and dom elements :D
  4. Worker responds back with a message, lets assume 2M which is now made anew in the main thread for a new 2M (yay), plus whatever fluff memory objects required to de JSONify the object... you see where this is going.

Since you said that this was a chrome app (another comment), then maybe you can restructure your code to make use of Transferable Objects to avoid the object Cloning creation of temporary objects etc. Course, to use transferable objects you'd have to restructure as an array buffer and that's a dark magic all of itself.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号