WebAssembly / shared-everything-threads

A draft proposal for spawning threads in WebAssembly
Other
29 stars 1 forks source link

Some feedbacks about Wasm threads #26

Closed fideltian closed 5 months ago

fideltian commented 6 months ago

Hey guys,

 Zoom's web client are based on Wasm multithread. we are very interested about the wasm native threads. i would like to share some feedbacks.

1) JS worker execution is based on event loop(onMessage). new worker(.....) could be executed until the current loop completed. Pthread workaround is to prepare the worker pool ahead to allow easily porting from c/c++. it is complex. 2) The JS worker event loop and Pthread event loop is separated. for example, pthread_condition_wait in c/c++ cannot be coexisted with onMessage of worker. it is lack of the similar idea of "I/O multiplexing" event loop. 3) If a native wasm thread, how to let native thread talk to the outside, such as webcodecs, webgpu,webgl, websocket,etc. 4) if a native wasm thread, SAB is still needed? SAB requires "cross origin isolated". it is a challenge for Wasm mulithread adoption on SDK market. personally, i hope the SAB could be optional for wasm native threads if possible.

tlively commented 5 months ago

Hi @fideltian, thanks for your comments.

We expect Web Workers to remain the only threading primitive on the Web, so unfortunately nothing currently in this proposal would help with (1) or (2).

For (2), you might want to look into JSPI, which will let you efficiently return to the JS event loop and resume your Wasm code in the future.

For (3), we're making sure that it will be possible for all threads to call JS imports. See the JS API section of the overview for the details.

For (4), yes, you will still need SAB and shared Wasm memories if you're using a language that compiles to use linear memory, so you'll still need COOP/COEP. I expect that the Web security folks will require the same headers even when using shared WasmGC instead of linear memory. Unfortunately the security policies there are not in scope for the Wasm community group.

syrusakbary commented 5 months ago

We expect Web Workers to remain the only threading primitive on the Web, so unfortunately nothing currently in this proposal would help with (1) or (2).

Can you expand on this @tlively ? I think this proposal is great (with some nits), but if browsers don't have a plan to implement it, then does it make sense to move it forward?

Or perhaps you meant that the API will not be accessible from JS directly? (but browsers will still be able to run Wasm with the shared-everything-threads opcodes?)

Any clarification here would help!

conrad-watt commented 5 months ago

@syrusakbary after feedback from V8, we've decided not to move forward with proposing a thread creation primitive in Wasm. We still plan to move forward with proposing and experimenting with everything that's described in this repository. On the Web, browsers will continue to use Web workers to create threads, and our proposed "shared-everything" language extensions will enable more things to be shared between these threads (e.g. function instances, GC structs). Outside the Web, new thread creation primitives taking advantage of our "shared-everything" extensions can be imported from the environment - e.g. this sketch of a suite of component model built-ins.

syrusakbary commented 5 months ago

Thanks for the incredibly fast reply @conrad-watt !

I think I understand what you mean, but let me rephrase things, to see if I got it right: V8 doesn't initially plan to support the new opcodes proposed by the shared-everything-threads proposal, however it will add support for Web Workers to share more things between threads (functions, GC structs, ...). EDIT (it seems that I misunderstood): V8 will support all the new opcodes proposed by the shared-everything-proposal, however it will not support the component model thread.spawn call.

Let me know if I got it right or I missed anything!

[!NOTE] This helps Wasmer a lot so we can plan for future work on the proposals, as our plan is to support exactly the same things as the Wasm runtimes in the browsers do (even though we are a non-web runtime!).

Another question, since this proposal will be included in the component model proposal, does this implicitly mean that V8 doesn't initially plan to support the component model natively? (if it's too early to respond, please feel free to dismiss the question... I'm just curious!)

rossberg commented 5 months ago

While I'm okayish with deferring a core-level thread creation instruction for a little longer, I'll assume we're all on the same page that this leaves a severe hole in the language that we will address soon enough.

tlively commented 5 months ago

Even going forward, I don't think a core-level thread creation primitive makes much sense without a story for how spawned threads could interact with the host environment, including when a host would have to opt-in to providing a thread safe (or duplicated per-thread) environment (as is the case in JS, but also potentially for other hosts).

I hope we can develop such a story, but so far the best we have is host calls to spawn threads.

tlively commented 5 months ago

Going to close this issue because all the questions have been addressed and I don't believe there are any outstanding decisions to be made here, but anyone should feel free to reopen it if they want to continue the discussion. Thanks again for your feedback, @fideltian!

rossberg commented 5 months ago

Even going forward, I don't think a core-level thread creation primitive makes much sense without a story for how spawned threads could interact with the host environment, including when a host would have to opt-in to providing a thread safe (or duplicated per-thread) environment (as is the case in JS, but also potentially for other hosts).

I hope we can develop such a story, but so far the best we have is host calls to spawn threads.

Aren't the sharing annotations enough for that purpose? In particular, they will prevent any thread created inside Wasm from calling into the host, unless the host was able to create shared functions on its end and pass them as imports. In an environment like JS, that would presumably not be possible (except for shared Wasm functions pulled from an instance), and that would be totally fine. Other environments (or even JS in some future) might be able to provide more general means to create host functions.

This would enable the internal use of threads for computational parallelism, while requiring host cooperation for external concurrency, which would reflect a natural difference between the two.

tlively commented 5 months ago

The sharing annotations give a story for how Wasm is prevented from interacting with the host in an unsafe way, but what we need here is a story for how Wasm threads can be enabled to interact with the host in a safe way. For a JS host, this requires setting up a separate JS environment on the new thread with new thread-local host functions available to call on the new thread. Unless we allow hosts to hook into the behavior of a thread.spawn instruction, they wouldn't be able to set up the environment properly on the new thread, but if you allow hooking the behavior, then you might as well keep it an import.

rossberg commented 5 months ago

One step at a time. In-Wasm threads are very useful in themselves, as an enabler for parallelisation. For that they generally don't need to be able to call into the host. I am not even convinced that such an ability is particularly important.

kripken commented 5 months ago

@rossberg Our problem on the Web is that without the ability to call into the host, we don't have a good idea for how to use wasm-only threads. To summarize some of the previous discussion:

So the worry here is to ship a complex feature on the Web that is either unused or that is used but causes regressions.

With that context in mind, I 100% agree with you that this is a current hole in the spec, that we want to fix it, and that we should fix it. We should keep working on it.