Opinion about synchronous requests in web workers
Asked Answered
K

2

16

I want to know what do you think about this. Is recommended to use synchronous requests (XMLHttpRequest) in a web worker? What problems can I find?

I have been testing this in my app and I haven't find any trouble. But I'm afraid of this synchronus behaviour because of old experiences with jQuery and AJAX. My app gets a big amount of data from several tables in a database, and this requires a time. For each bunch of data retrieved from a table, I need to instantly process it to not delay the whole thing too much. Meanwhile, the user is interacting with the browser, so it can be blocked, and I thought that web workers would work fine. Do you thing that this is a good solution? Or should I try with asynchronus requests?

Thank you.

Koral answered 28/12, 2012 at 10:24 Comment(3)
It is possible...and depends on your requirements, though AJAX wouldnt be AJAX without the asynchronous!!!Denitrify
I can't recommend SJAX (synchronous javascript and XML) but I'd like to see some hard facts too, and my concerns don't reflect the behavior in multi-threaded environment.Braunschweig
Thank you guys. I know the meaning of the A in AJAX :) but I have seen many people doing something like this when they are using web workers.Koral
D
20

I don't have hard facts, but since you asked for opinions... :)

There is a telling issue in Chrome: Too many Web Workers can cause a silent crash (caps ~60-100, according to this bug report). The general problem is Web Workers are resource intensive, at least with v8.

Assuming you're going to end up making multiple HTTP calls, if you're doing synchronous HTTP calls in a Web Worker:

  • In a sense, you're trading asynchronous HTTP calls for asynchronous Web Workers, which will only be adding another intermediary into the mix and you still have to manage things asynchronously.
  • If you go the simpler and more resource efficient route and only use one Web Worker you'll spend a lot of time waiting for it to give you responses.
  • If, on the other hand, you use multiple Web Workers you will likely need to keep track of which one is free, which one is busy, etc., in which case you will be creating a home-grown scheduler instead of using what comes baked into the browser.
  • Finally, Web Workers are expensive (apparently), and you might end up creating multiple Web Workers just so they can sit around and wait for an HTTP call to finish.

I do not consider myself an expert on the matter, so please take this for what it's worth.

Update: Adding some pros / cons for various scenarios.

Some pros / cons that come to mind when choosing between making synchronous and asynchronous HTTP calls when using a Web Worker:

  • Generally, synchronous requests will be easier to write and will result in code that is easy to follow. A downside of synchronous requests is they might encourage writing long functions that should be carved out into separate, smaller functions.
  • If you're making a single call, there is no difference in the time it takes to finish between the two methods and synchronous is better because it's a bit simpler. I say it's only a bit simpler because a single asynch call with one callback listener is really rather simple.
  • If you're making multiple calls that have to happen in a specific sequence, like loading a user's profile data and then getting the local weather based on their address, synchronous calls will be better because it will be easier to write and a lot easier to read. The main thing about reading it is the sequential dependencies in the calls will be clearly outlined by the choice of making the calls synchronously and their order in the function. The more calls there are, the more this will matter. If there are many calls, the difference in complexity is likely to be drastic.
  • If you have to make multiple calls that do not need to happen in any specific order, then asynchronous requests are better because the overall process is likely to be orders of magnitude faster than with synchronous requests. The more calls you're making or the slower the connection, the more significant the difference in total elapsed time will be; this difference will grow very quickly (exponentially?). From the perspective of someone reading the code, I think using synchronous requests, in this situation, would be somewhat misleading as it would suggest there is a sequential nature to the calls even though there is not. From the perspective of writing a series of asynch requests that are not dependent on each other, it shouldn't be too bad because you just setup a counter, make all the calls, increment the counter in each of the callbacks and you're finished when the counter equals the number of calls you made.

Update: @rbrundritt makes a very interesting and relevant observation in a comment on this answer:

One thing I found working with web workers is that they appear to each gain their own http limit. Browsers limit the number of concurrent http requests to around 8 or 12 depending on the browser before throttling, which can be a bottle neck if you have a lot of requests to process. I've found that if I pass my requests web workers, each can do 8 to 12 concurrent requests before they start throttling. This can be a huge benefit for some apps.

@rbrundritt

Dibasic answered 28/12, 2012 at 12:6 Comment(8)
Nice. Althought you say that you are not an expert on the matter, your opinion is very interesting.Koral
Maybe I didn't explain all the details. I want a unique web worker to do this task on the background. I mean, a web worker with a for loop to retrieve data from each table, do some parsing and more stuff. This works well with synchronous calls, but I think that I have to use some callback functions if I want to use asynchronous calls (is this better?). This is not the only web worker in my app, there is at least one more running at the same time to do other scheduled tasks. Do you think that the use of web workers is not justified in this case? Thanks.Koral
Thx for the details. Web Workers are great and I don't mean to imply they should be avoided. Sounds like it makes great sense to use one for this. Question to me is whether it makes sense to use sychronous XHRs. It will be less asynch programming because you only have to start / stop the Web Worker instead of starting and handling the XHRs, too. Really boils down to if that is worth the process taking longer? Potentially much longer if you have many HTTP calls to make. I don't see the downside of using asynch HTTP requests, unless you only need one.Dibasic
That's the point. What happens if I use synchronous requests inside a web worker? Any benefits/risks with this? I really like your last two sentences. Than you again.Koral
Np. I updated the answer to expand on synch vs. asynch, a bit.Dibasic
@tiffon, Re "trading asynchronous HTTP calls for asynchronous Web Workers" is key. Putting them in workers or a worker pool allows you to do custom ordering of requests. If there's no need for that, then the benefit is lessened.Aversion
One thing I found working with web workers is that they appear to each gain their own http limit. Browsers limit the number of concurrent http requests to around 8 or 12 depending on the browser before throttling, which can be a bottle neck if you have a lot of requests to process. I've found that if I pass my requests web workers, each can do 8 to 12 concurrent requests before they start throttling. This can be a huge benefit for some apps.Lapstrake
@Lapstrake – Awesome. Really interesting and relevant point. I'm going to call it out in the answer, lmk if you take issue with that.Dibasic
L
1

I just wanted to add a note (that is too long for a comment) that the limit of ~60 web workers mentioned in @tiffon's answer doesn't appear to exist in Chromium anymore. I can create 500 workers in Chrome like this with no errors/crashes:

let workers = [];
for(let i = 0; i < 500; i++) {
  let worker = new Worker(URL.createObjectURL(new Blob([`console.log('cool${i}')`])));
  worker.postMessage({});
  workers.push(worker);
}
await new Promise(r => setTimeout(r, 15000));
for(let i = 0; i < workers.length; i++) {
  workers[i].terminate();
}

Though, it's hard to imagine a situation where hundreds of workers would be appropriate, given core counts don't currently go higher than around 64.

Lonesome answered 15/5, 2019 at 9:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.