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.
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.
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.
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.
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)
).
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With