HTML5/JS - Start several webworkers

12,674

1. How would I run several web workers? I tried a for-loop looking like that:

There's no problem with creating more than one worker, even if you don't keep track of them in an array. See below.

2. How would I control that all have finished their work? (I need to reassembly the array and work with it later)

They can post a message back to you when they're done, with the results. Example below.

3. How many web workers really bring an improvement?

How long is a piece of string? :-) The answer will depend entirely on the target machine on which this is running. A lot of people these days have four or more cores on their machines. Of course, the machine is doing a lot of other things as well. You'll have to tune for your target environment.

4. Is there any advanced tutorial, besides the MDN-entry?

There isn't a lot "advanced" about web workers. :-) I found this article was sufficient.

Here's an example running five workers and watching for them to be done:

Main window:

(function() {
    var n, worker, running;

    display("Starting workers...");
    running = 0;
    for (n = 0; n < 5; ++n) {
        workers = new Worker("worker.js");
        workers.onmessage = workerDone;
        workers.postMessage({id: n, count: 10000});
        ++running;
    }
    function workerDone(e) {
        --running;
        display("Worker " + e.data.id + " is done, result: " + e.data.sum);
        if (running === 0) { // <== There is no race condition here, see below
            display("All workers complete");
        }
    }
    function display(msg) {
        var p = document.createElement('p');
        p.innerHTML = String(msg);
        document.body.appendChild(p);
    }
})();

worker.js:

this.onmessage = function(e) {
    var sum, n;
    sum = 0;
    for (n = 0; n < e.data.count; ++n) {
        sum += n;
    }
    this.postMessage({id: e.data.id, sum: sum});
};

About the race condition that doesn't exist: If you think in terms of true pre-emptive threading, then you might think: I could create a worker, increment running to 1, and then before I create the next worker I could get the message from the first one that it's done, decrement running to 0, and mistakenly think all the workers were done.

That can't happen in the environment web workers work in. Although the environment is welcome to start the worker as soon as it likes, and a worker could well finish before the code starting the workers finished, all that would do is queue a call to the workerDone function for the main JavaScript thread. There is no pre-empting. And so we know that all workers have been started before the first call to workerDone is actually executed. Thus, when running is 0, we know they're all finished.

Final note: In the above, I'm using onmessage = ... to hook up event handlers. Naturally that means I can only have one event handler on the object I'm doing that with. If you need to have multiple handlers for the message event, use addEventListener. All browsers that support web workers support addEventListener on them (youdon't have to worry about the IE attachEvent thing).

Share:
12,674
stiller_leser
Author by

stiller_leser

Updated on July 23, 2022

Comments

  • stiller_leser
    stiller_leser almost 2 years

    I'm currently writing on a program, where I have to deal with huge arrays. I can however split those arrays. My plan now is, to process the arrays in different web workers. I have however never worked with them and do have several questions:

    1. How would I run several web workers? I tried a for-loop looking like that:

    for(i = 0; i < eD.threads; i++){
        //start workers here 
        var worker = new Worker("js/worker/imageValues.js");
        worker.postMessage(brightness, cD.pixels[i]);
    }
    

    Here I do get the error, that the object couldn't be cloned. Which seems logical. I guess it would be better to save them in an Array?

    2. How would I control that all have finished their work? (I need to reassembly the array and work with it later)

    3. How many web workers really bring an improvement?

    4. Is there any advanced tutorial, besides the MDN-entry?

    Thank you!

  • stiller_leser
    stiller_leser over 10 years
    Hi, thanks for your answer. I'm going to work through it. The pieces of String is actually imagaData of a canvas turned into a string. For a resolution of 1300 * 1700px you end up with an array with the length of 8840000. So I figured I split the array into x pieces (depending on a user controllable number of threads). Each part of the whole array is going to be processed. Afterwards the imageData-array is rebuild and drawn onto a canvas. At least according to my plan :D
  • T.J. Crowder
    T.J. Crowder over 10 years
    @stiller_leser: Sounds like the kind of thing web workers were meant for. :-) But I wasn't actually talking about strings in the computer sense. "How long is a piece of string?" is a British idiom, basically meaning "There are too many variables to answer that."
  • stiller_leser
    stiller_leser over 10 years
    :D - I didn't expect an idiom here. Haven't had too many idioms in school, so long: You live and learn.
  • meawoppl
    meawoppl almost 10 years
    Also notably for anyone finding this tread. Canvas element have special passing semantics now, so serializing to a string is no longer necessary :)
  • meawoppl
    meawoppl almost 10 years
    This link is good overview, the "transferrable objects" section is the part that you are interested in.
  • T.J. Crowder
    T.J. Crowder almost 10 years
    @meawoppl: LOL, I had that link in the answer! I just didn't remember transferrable objects. :-) Thanks!