1

I'm working on a canvas application that uses 2 web-workers to calculate some frames. You can see below how each worker sends a specific frame back to the main thread.

worker logic

On the main thread I have an event listener for each worker. They listen for the frame, and when they receive it, they send it to a function called drawFrameToCanvas

This seems simple enough, but my problem is these webworkers can send their data out of order. So worker2 can finish before worker1

The way I thought to fix this problem is like this:

var desiredFrame = 0;
function drawFrameToCanvas(frameData, frameNumber){

  if(frameNumber != desiredFrame){ //this is the wrong frame
    //wait until it's the correct frame
    setTimeout(function(){ drawFrameToCanvas(frame, frameNumber) }, 10);
  }

}

However by the time frame 0 is finished, frame 1 has been requested to be drawn several times. So this didn't work. I then thought about making an object that would store the frame data and have the drawFrameToCanvas function call for this object.

However I couldn't think of a good way to do this without storing all the frames in memory as this object would always be referenced and never cleared for garbage collection.

Is there a better way to call javascript functions in these circumstances?

4
  • Do these workers keep sending values or is it a one time thing? If they keep sending values, do you always need them to alternate and be in order? Commented Jul 27, 2018 at 2:34
  • @yts Yes they keep sending values in alternating order, and that order has to be kept through the applications lifespan Commented Jul 27, 2018 at 3:05
  • Can you discard results, if any of the workers delivers in succession before the other one? If so, you can just ignore worker 1 while worker 2 is supposed to deliver a result until worker 2 delivers a result and vice versa. Commented Jul 27, 2018 at 17:10
  • @FK82 discarding results would mean discarding entire frames. The only way to get those back would be to have the workers make them again, so I don't think it's a good option. Commented Aug 10, 2018 at 3:48

1 Answer 1

1

You can create queues for the results, and remove the data from the queues as they're processed to avoid the memory issues you mentioned. Something like this:

var worker1Results = []; 
var worker2Results = [];

worker1.onmessage = function(e){
    worker1Results.push(e.data);
    performActionWhenBothDone();
}

worker2.onmessage = function(e){
    worker2Results.push(e.data);
    performActionWhenBothDone();
}

function performActionWhenBothDone(){
    if (worker1Results.length && worker2Results.length) {
        performAction(worker1Results.shift(), worker2Results.shift());
    }
}

function performAction(worker1Result, worker2Result){
    //drawFrameToCanvas code
}
Sign up to request clarification or add additional context in comments.

2 Comments

That works well and is very simple, thank you! After some testing by setting the arrays to null I can confirm the garbage collector is doing it's job
@YAHsaves Great! Glad it helped. Because .shift() is being called, the worker responses are being removed from the arrays and will no longer be referenced, readying them for garbage collection. So, all that would be left in memory are two empty arrays, which shouldn't be a problem.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.