bjorn3 / browser_wasi_shim

A WASI shim for in the browser
Apache License 2.0
307 stars 41 forks source link

Does this support threads? #46

Open temeddix opened 1 year ago

temeddix commented 1 year ago

Hi, thanks for this wonderful effort :)

I'm very interested in running thread code from WASI .wasm file on the browser. Is it possible right now? If not, can I make a PR for that using web workers?

bjorn3 commented 1 year ago

Threads are not yet supported. I do want to support them, but I don't think it will be a trivial change. webworkers don't allow sharing javascript objects, so directly sharing the Fd list between all threads is not possible. Instead some way of keeping them on a single thread and then doing message passing whenever another thread wants to call a method on it will be necessary. The standard message passing way for webworkers is asynchronous and webassembly is fully synchronous, so using that method won't be possible afaik. Instead I think it will be necessary to manually implement a message queue on top of SharedArrayBuffer which can block threads using Atomics.wait/Atomics.notify. See also https://github.com/bjorn3/browser_wasi_shim/issues/14.

temeddix commented 1 year ago

Yeah, I am aware that message passing is crucial between web workers to send messages in JS. However in native languages like Rust, you can simply share native channels inside WebAssembly.Memory and communicate using them. IMO, All we have to do is to ensure that all the new web workers share the same WebAssembly.Memory and provide some spawn mechanism for native functions with SharedArrayBuffer.

I think we should guide the users about only two things:

  1. Provide the WebAssembly.Memory that this shim library will use, when instantiating wasm with this shim(Perhaps this can be automatically done).
  2. Be sure to set the proper cross-origin related headers when using the thread feature.

I have experience with web workers and SharedArrayBuffer from Rinf and async_wasm_task (I'm the maintainer). I'm also very familiar with typescript. May I work on this idea and create a PR, if acceptable?

temeddix commented 1 year ago

I'll leave the relevant links

bjorn3 commented 1 year ago

Provide the WebAssembly.Memory that this shim library will use, when instantiating wasm with this shim(Perhaps this can be automatically done).

There are two shared memories that are necessary. One shared between the wasm instances for each thread and one for the message passing. browser_wasi_shim can't use the shared memory used by wasm for message passing as that would likely cause corruption for the wasm module if it thinks it can write to memory while at the same time browser_wasi_shim is using it for the message passing.

I think it would be possible to have a method on WASI (Or maybe we should have a separate SharedWASI) which returns an Object containing all necessary SharedArrayBuffer and Webassembly.Memory instances which can be passed to postMessage and on the other side can be turned back into a WASI (or SharedWASI) instance. Or alternatively we could have browser_wasi_shim ship with a webworker which is used for all thread spawning attempts and handles all this passing behind the scenes. This would be less flexible though.

May I work on this idea and create a PR, if acceptable?

Absolutely!

oligamiq commented 1 month ago

Having trouble with synchronization? Although old-school, partytown uses an interesting trick to achieve synchronization. Of course, you can also use Atomics.

https://dev.to/adamdbradley/how-partytown-s-sync-communication-works-4244

bjorn3 commented 1 month ago

Blocking http requests to a service worker is an interesting hack. I'm afraid it will deadlock if a service worker gets a channel message (for sending non-serializable things like the shared memory to write to) and http requests to service in the wrong order. And it also doesn't really help with the debugging side of things. Any multithreading makes debugging so much harder with current browser debugger implementations. I tried implementing thread support a while back, but hit several debugger crashes, broken single stepping behavior, breakpoints not working and other bugs.