Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If i send multiple messages to the same webworker, does it queue them up and process them sequentially?

As the title says...

Basically, if I have a single webworker and post it 1000 messages at once.

Each message results in the worker performing a processing intensive operation.

Am I best to post each message to the webworker sequentially after the previous one completes, or can I safely send all the requests over to the worker knowing that they will just be processed and returned one by one as they complete?

If I do this am I better off implementing a queueing system within the worker? or is it not necessary?

I understand that this single worker is only a single thread and therefore the javascript operations will indeed occur synchronously within the webworker itself, but I am concerned about contention in a similar way that performing 200 ajax requests at once would overwhelm a browser.

I hope this makes.

like image 219
gordyr Avatar asked Feb 19 '15 13:02

gordyr


People also ask

How many web workers can run concurrently?

A web worker is a JavaScript program running on a different thread, in parallel with main thread. The browser creates one thread per tab. The main thread can spawn an unlimited number of web workers, until the user's system resources are fully consumed.

How do web workers work?

A web worker is a JavaScript that runs in the background, independently of other scripts, without affecting the performance of the page. You can continue to do whatever you want: clicking, selecting things, etc., while the web worker runs in the background.

Is web worker a thread?

Web Workers are a simple means of running scripts in background threads for web content. Without interfering with the user interface, the worker thread may perform tasks.


2 Answers

The worker will queue up messages (specifically, it will queue up calls to onmessage) and process each message when ever the worker's call stack is empty.

This means, however, that asynchronous operation could result in input multiple messages being processed before any any particular operation is completed. For example:

onmessage = function(e) {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "/" + e.data);
    xhr.onload = function() {
        postMessage(xhr.responseText);
    }
}

If you passed in 1000 messages at once, I suspect the browser will fire off 1000 Ajax requests (or at least a lot of requests) before it runs postMessage inside of onload. This is because onload does not run until the Ajax call is complete, and each onload call will be added to the event queue behind any pending calls to onmessage that were requested before the Ajax fetch could complete.

If you wanted to ensure that only one Ajax request is out at a time, you could indeed implement an internal queue that moved only when onload was called:

var queue = [];
var busy = false;

onmessage = function(e) {
    if(busy) {
        queue.push(e);
    }
    else {
        busy = true;
        runAjax(e);
    }
}

var runAjax = function(e) {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", e.data);
    xhr.onload = function() {
        postMessage(xhr.responseText);
        if(queue.length) {
            // run the next queued item
            runAjax(queue.shift());
        } else {
            busy = false;
        }
    }
}

In this case, the first messages goes into the else block, which sets busy = true and runs the Ajax fetch. The following 999 messages are routed to the if block, because busy is true (and will not become false until the Ajax request completed and queue is empty). The queued messages are handled only after an Ajax request is complete.

If you wanted to tolerate more than one Ajax request at the time, you could use a counter instead of boolean: use busy++ and busy-- instead of setting true and false, and test that the current number of outstanding connections has not reached your allowed max (i.e., if(busy == 5) instead of if(busy)).

like image 133
apsillers Avatar answered Sep 29 '22 21:09

apsillers


The Web Worker receives each message one at a time - any queuing would be done by your own logic - for speed its best to transfer data as typed arrays especially a form called Transferable Objects - possibly you could put many (1000) messages into such a typed array (float or int) and make it a single message - the actual data transfer from browser to Web Worker or vice versa is quite fast - typed array of 10's of mbyte in milliseconds or less ... this messaging does handle objects as well albeit with a speed penalty compared to low level typed arrays

like image 37
Scott Stensland Avatar answered Sep 28 '22 21:09

Scott Stensland