
Multithreading Rust and Wasm - alexcrichton
https://rustwasm.github.io/2018/10/24/multithreading-rust-and-wasm.html
======
ilovecaching
I'm extremely bullish about Rust riding wasm the same way Go rode the
container space. This kind of work is exactly why I feel that way. It's
uniquely positioned to take advantage of the benefits of wasm; building
faster, safer applications on the browser.

I look forward to the day when the web is Rust, although I guess if you're
using Firefox, that's already partly true. :)

------
amelius
The ultimate test would be to see if it is possible to implement an efficient
concurrent GC in Rust+WASM. This might require memory fence instructions in
WASM.

~~~
monocasa
I thought you didn't have raw stack access in wasm, making efficient
concurrent GCs impossible practically in native wasm.

Hence the GC work to give a higher level API that can more easily be
sandboxed.

~~~
amelius
Virtualization technology is quite mature now, and allows running low-level
code (that can access the stack) with safety. Servers run this type of code
all the time!

Why would we throw away these achievements, and turn WASM (with its
potentially simple instruction set) into a complicated monster, that's prone
to security problems through its complexity alone?

Also, language designers do not _want_ a GC embedded in their assembly
language; they want to implement it themselves, using their own constraints.

~~~
monocasa
> Why would we throw away these achievements, and turn WASM (with its
> potentially simple instruction set) into a complicated monster, that's prone
> to security problems through its complexity alone?

Because sandboxing in process is difficult otherwise. You can't allow the user
to control code pointers, but for performance reasons you both need to have
the raw pointers on the stack, and need to have semi privileged code in the
same process just a function call away. Throwing everything into the
process/hardware virtualization models doesn't fit this use case very well.
It's why the VM in browsers carefully controls code pointers _and_ is already
pulled out to a semi sandboxed process.

And I'll grant you that language implementors want raw stack access to
implement their own performant GC; that just doesn't exist yet in wasm.

------
joelhooks
Nik Graf releases this free egghead video course a couple weeks ago on Rust
and WASM. [https://egghead.io/courses/using-webassembly-with-
rust](https://egghead.io/courses/using-webassembly-with-rust)

------
kodablah
Nice, was just reading your issue [0]. I spent a bit of time the other day
thinking how I could implement these thread ops on the JVM (JVM rambling
henceforth, skip if not curious)...

First, my project's output requires no runtime/dependencies, so I am
restricted to JVM libs only. Memory is implemented as a ByteBuffer which does
not have atomic access. I didn't quite understand the threads spec wrt data
init on mem so I'll have to get clarification there (lock all mem? just go and
pray?). The implementation will create four synthetic methods in the class:
lock, unlock, wait, and wake. The class will have a field that is
ConcurrentMap<Integer, int[]> where the key is the mem offset being locked,
and the value is an array of mutable int refs size 2, the first being lock ref
count and the second being wait ref count. Imports of shared memory pass that
around along w/ the ByteBuffer.

Lock will create/incr ref count and secure the lock via monitorenter on the
int array (or fail if ref > 0 when just a try). Unlock will monitorexit and
decr the count (removing from map if both ref counts are 0). All ops are done
between this lock/unlock. Wait/wake is via wait/notify on the JVM, but JVM has
no construct to say how many or if any threads were woken up on notify, so I
have to keep the wait count. Incr/decr on the ref and wait vs notify (in a
loop if > 1) is done as expected using wait() and notify() on the array
itself. The lock, unlock, wait, and notify are done w/in concurrent map's
compute making them atomic. Lock/wait lazily create the refs in the map.
Unlock/notify, upon reaching 0 for both refs at the end, clear the refs out of
the map.

I have looked into existing JVM constructs and this seems to be the best way
(I wish I could use Guava's Striped or the like, but I have no
dependency/runtime requirement on outputted class files). Countdown latches,
other locks, conditions, etc were all runtime overkill. I could have better
performance than a boxed-int map with some extra code but wanted to keep it
simple. Granted this is all pie-in-the-sky thinking, the impl will change it
for sure.

I am afraid to start an implementation because the proposal isn't further
along yet (I really need some test cases in the suite to make me feel better).

0 -
[https://github.com/WebAssembly/threads/issues/106](https://github.com/WebAssembly/threads/issues/106)

------
klarifie
The article title is misleading. Wasm will not support multithreading, rather
it'll be multiprocess via web workers and shared arrays for communication.
It's not a single address space - code or data.

~~~
jamesfmilne
The threads can all use the same SharedArrayBuffer for their memory, and thus
a single address space.

If the SharedArrayBuffer wasn’t shared, what’s the point of the atomic
instructions, etc.

~~~
jamesfmilne
From TFA:

WebAssembly modules today are optionally associated with at most one instance
of “linear memory”. In non-wasm parlance, you can put a stick of RAM into a
wasm module. This WebAssembly.Memory is today always backed by an ArrayBuffer,
but you’ll soon be able to flag a memory as “shared” which means it’s backed
by SharedArrayBuffer instead. This subsequently means that the structured
clone of a WebAssembly.Memory backed by a SharedArrayBuffer will refer to the
same memory!

~~~
klarifie
This is analogous to different UNIX programs communicating with shmget and a
synchronization primitive. It's still a multiprocess model.

~~~
monocasa
At that point, the distinction between threads and processes gets really muddy
even when you're not using wasm. clone(2) is just a superset of fork(2) that
lets you decide whether to share memory or not (among other resources).

~~~
namibj
I still think one could use a stackless clone(2) to get rid of the TLB flush
when using threaded open(2). It would need to live without using the stack
inside the clone however, and that's rather ugly to program.

------
eridius
If the very first thread that's created has to do some bookkeeping that the
other created threads rely on, what happens if you create a second thread at
the same time as the first one? Or in other words, what happens if you don't
instantiate the module on the browser's main thread at all, but instead just
spin up 2 web workers that each instantiate the module? Whichever starts first
will be thread 0, but what's to stop the other worker from entering its
`start` function while the first worker is still busy initializing memory?

------
davidhyde
Nice article. Now I know why the ManualResetEventSlim didn't work in c#
Blazor. I wasn't aware that multi-threading in wasm was work in progress.

The demo doesn't work on the standard latest firefox yet unfortunately (ver
63.0). Error: "this browser does not have SharedArrayBuffer support enabled".
I guess this is a nightly firefox build thing.

~~~
sertorius
> this browser does not have SharedArrayBuffer support enabled

It was disabled for Spectre safety reasons, but it can be re-enabled by
navigating to "about:config", searching for "javascript.options.shared_memory"
and toggling it to enabled. (But it was obviously disabled for good reason, so
might want to enable it temporarily)

~~~
davidhyde
Thanks! That fixed that problem. Except now I get "this browser does not
support passive wasm memory". There aren't any obvious javascript.options.*
options for that.

~~~
alexcrichton
Oh dear sorry about this, it's a little too non-obvious how to see the demo!
I've [pushed a small commit]([https://github.com/rustwasm/wasm-
bindgen/commit/f016ae5846bf...](https://github.com/rustwasm/wasm-
bindgen/commit/f016ae5846bfc922014c58eeea3b3b62e3f7bed1)) to update the demo
to include information about browser requirements. Today this demo requires
Firefox Nightly (64) and requires the `javascript.options.shared_memory`
feature to be enabled. Other browsers will likely soon be able to run the demo
as well!

~~~
davidhyde
Thanks, I'll give that a go!

------
jxub
Goddamn, the frequency of Rust-related articles on the front page must be
really telling something positive about this language and its community.

~~~
jimmy1
> must be really telling something positive about this language and its
> community.

It's because it's the new shiny thing. This basically used to be a ruby on
rails post-it board, then C# for a while, then Java when Java 8 Streams were
announced, then Go, etc.

I am not saying it's a bad thing -- in fact I can't wait to go through that
"write an OS in Rust" blog that was posted here earlier -- but no I don't
think it's telling of anything quite yet.

~~~
zellyn
It's not just because it's shiny. Rust happens to (a) be a great fit for the
parts of WebAssembly that have been implemented so far (partly because it
doesn't need GC), and (b) have done a really good job of building WebAssembly
tooling with nicer ergonomics than other languages.

~~~
seanmcdirmid
WASM is the new and shiny also. I'm not even sure what to do with it ATM given
that the DOM story still hasn't been figured out.

~~~
mnemonik
There is a DOM story: host bindings. It just isn't implemented yet.

However, that doesn't mean that you can't use it now. wasm-bindgen is
essentially a polyfill for host bindings plus some other little things.

Some resources to check out if you want to learn more:

* Host bindings: [https://github.com/WebAssembly/host-bindings/blob/master/pro...](https://github.com/WebAssembly/host-bindings/blob/master/proposals/host-bindings/Overview.md)

* More info about web-sys (web-sys is like the raw libc for the web): [https://rustwasm.github.io/wasm-bindgen/web-sys/index.html](https://rustwasm.github.io/wasm-bindgen/web-sys/index.html)

* API documentation for web-sys: [https://docs.rs/web-sys/0.3.2/web_sys/](https://docs.rs/web-sys/0.3.2/web_sys/)

* DOM hello world example: [https://rustwasm.github.io/wasm-bindgen/examples/dom.html](https://rustwasm.github.io/wasm-bindgen/examples/dom.html)

* A mini MS Paint style example: [https://rustwasm.github.io/wasm-bindgen/examples/paint.html](https://rustwasm.github.io/wasm-bindgen/examples/paint.html)

* An FM synth in WebAudio: [https://rustwasm.github.io/wasm-bindgen/examples/web-audio.h...](https://rustwasm.github.io/wasm-bindgen/examples/web-audio.html)

