Do async frameworks ( like tokio ) support WASM, particularly multithreading in the browser?

I'm very curious. Do async frameworks like tokio support WASM? Both single-threaded and multithreaded runtimes? Any corner cases? Is it okay to use in production for the web front-end?

Full runtimes like tokio and async-std can't be fully functional in the browser since a bunch of the APIs they use to wait on tasks aren't available. WASM currently has no concept of threads which would make most of a full runtime sort of overkill anyway.

There are crates like wasm-bindgen-futures that bridge to the JavaScript Promise system though.

2 Likes

Essentially, the browser event loop is the “async framework” in this case, and you use wasm-bindgen-futures to interact with it. You can't bring your own main loop.

(It is possible to get multithreading in WASM/web, but it uses web-workers and shared memory, plus more experimental features — see Parallel Raytracing - The `wasm-bindgen` Guide for some info on that possibility. It's definitely not something you should use for a production application, yet. You do not need threads to run async tasks.)

4 Likes

Thanks for both answers.

@semicoleon @kpreid

Okay. But what about multi-threading / multiprocessing? How to get it? Just use a pool of threads? Which do you recommend if code should be portable on the web?

There isn't anything like a thread in the current set of standard web APIs. You can use web workers as previously mentioned, but those are a little closer to processes than threads in terms of setup and isolation.

2 Likes

So what would be a proper solution for a commercial project?

Depends on what you're doing. The vast majority of commercial web products do all of the heavy lifting server side where they have more control.

There's nothing wrong with using web workers, but you're going to have to experiment with how to set up your code if you want it to be usable both on the web and in a more traditional rust executable. I'm not aware of any examples off the top of my head, though I'm sure they exist.

1 Like

The only time you really need threads is if you are running a CPU-intensive workload which cannot practically be split into small pieces, or which has to happen absolutely as fast as possible. Most web applications do not need anything like that. As @semicoleon said, often the heavier work happens on the server, but also, it is very likely that whatever you are thinking of doesn't need threads.

One of the main purposes of async programming in Rust is to allow only one thread to be efficiently used for many activities; in the web/JS world, using that single thread that way is the normal case.

Don't assume that there is a problem here that needs fixing. Write your application; use async with wasm-bindgen-futures and async/promises in the JavaScript parts of your code, and see how well it works. If it is too slow, you can look into workers, but first try optimizing your code, because that adds less system complexity. (And saves energy — phone users will appreciate your code not draining their battery!)

3 Likes

Lets' assume it's multimedia processing, and yes, it's CPU-intensive. Also, I also target desktops and would prefer not to rewrite my code for different platforms. Let's assume a single thread is a go at all. Any recipes for this?

Can you be more specific than “multimedia processing”? In particular, what is the source and destination? (Camera? Network stream? In-memory data? Data downloaded as a video or audio file?), and what processing are you doing to it? This will make a big difference to what the best solution is.

For an example of how it can matter, if you wanted to do real-time audio processing using a custom algorithm, you would want to do that in an AudioWorklet rather than anything else, because that's how you get lowest-latency access to audio input and output.

3D graphics. Multidimensional algorithms.

The best solution for 3D graphics is usually to let the GPU do as much of the work as possible. That's like using a thread, in that the GPU runs concurrently with the main CPU, but it is a very different programming style than just starting threads.

The good news is, this is well supported. Check out wgpu for a GPU interface that is high-level, efficient, and supports WASM/web.

Yes, I know :slight_smile: in fact I'm GPU Engineer. But CPU multi-threading matters.

Then you may have uses for web-workers. But this is an area which is still very new and experimental in some ways. Do not expect there to be one correct answer to “what should I use for a commercial project” — even the big companies will be experimenting, and perhaps writing/forking libraries/bindings/toolchains to make it work.

2 Likes