12 ms·
A Taste of JavaScript's New Parallel Primitives
- kbenson 10y ago> This leads to the following situation where the main program and the worker both reference the same memory, which doesn’t belong to either of them: If only Mozilla had some technology that could deal with ownership of memory... Seriously, if rust doesn't have an ASM.js optimized target yet, it really should.
- seibelj 10y agoIf rust can be compiled to LLVM, then emscripten can be the backend to asm JS
- steveklabnik 10y agoThe issue is emscripten uses a different LLVM version than we do; so it can work, but it's got some rough edges. We want both compile to JS and compile to wasm to work well, the work just isn't done yet.
- izym 10y agoI would be very surprised if Rust doesn't target WebAssembly sometime in the future. It's just such a good fit. If I remember correctly there are already talks about doing MIR->WASM.
- spicyj 10y agoIt's planned. https://github.com/rust-lang/rust/issues/33205 https://github.com/rust-lang/rust/issues/33205
- kibwen 10y agoWe Rust folk have definitely got plans in this space. :)
- pfooti 10y agoYou know, I'm not entirely sure how I feel about this. On the one hand: yeah, I get that having really multithreaded stuff is pretty handy, especially for certain computationally-bound tasks. On the other hand, I quite like the single-threadedness of javascript. Promises-based systems (or async/await) give us basically cooperative multitasking anyway to break up long-running (unresponsive) threads without worrying about mutexes and semaphores. I understand exactly when and where my javascript code will be interrupted, and I don't need to wrap blocks in atomic operation markers extraneously. I've written plenty multithreaded code, starting with old pthreads stuff and eventually moving on to Java (but my own experience with threaded stuff is limited mainly to C and Java), and it can be a real pain. I guess limiting shared memory to explicitly named blocks means you don't have as much to worry about vis-a-vis nonreentrant code messing up your memory space. That said, it is a pretty useful construct, and I see where this can benefit browser-based games dev in particular (graphics can be sped up a lot with multicore rendering, I bet).
- ihsw 10y agoWelp, the idea is portability. This is a bridge between other platforms into JS, and -- as you mentioned -- its usage is largely specialized. Most people don't really know what typed arrays are, but they're in ES6 nevertheless.
- deleted 10y ago[deleted]
- zzzcpan 10y ago> I understand exactly when and where my javascript code will be interrupted That's why callbacks, promises, async/await and all that are neither multitasking, nor multithreading. They are all about control, while multithreading is all about parallelism and is essentially a very low-level specialized thing, that nobody should be using, unless absolutely necessary.
- pfooti 10y agoWell, I'm old enough to remember coding for Mac OS 8, where "multitasking" was indeed cooperative - I had to say "oh, you can interrupt me here, if you want" at different places in my code, which meant bad actors could lock the system of course. It wasn't great. On the other hand, in the uncommon event I do have some weird javascript thing that's going to take a long time (say, parsing some ridiculously-big JSON blob to build a dashboard or something), I know I can break up my parse into promises for each phase and that I won't be locking up other UI processing as badly during that process. So: not exactly multitasking / threading as you say, but still a handy thing to think about.
- seibelj 10y agoThis is the last piece needed to allow multi-threaded code with shared state to emscripten [0]. A very good thing indeed [0] http://kripken.github.io/emscripten-site/docs/porting/guidelines/portability_guidelines.html http://kripken.github.io/emscripten-site/docs/porting/guidel...
- seibelj 10y agoThis is the last piece needed to allow multi-threaded code with shared state to emscripten [0]. A very good thing indeed [0] http://kripken.github.io/emscripten-site/docs/porting/guidelines/portability_guidelines.html http://kripken.github.io/emscripten-site/docs/porting/guidel...
- kgr 10y agoI'm excited to see progress in the area of JS concurrency, but I'm not sure how useful this is going to be. It lets me share ArrayBuffers between workers, but all of my data is in the form of Objects, not primitive arrays. One place where I would like to use this is for collision detection, like in this example: http://codepen.io/kgr/pen/GoeeQw http://codepen.io/kgr/pen/GoeeQw But I'm relying on objects with polymorphic intersects() methods to determine if they intersect with each other, and once I encode everything up as arrays, I lose the convenience and power of objects.
- phpnode 10y agoHere's a typed objects system for JS which uses ArrayBuffers for backing storage, in future it will also support SharedArrayBuffer - https://github.com/codemix/reign https://github.com/codemix/reign (disclaimer: I wrote this).
- ryandvm 10y agoThe saving grace of JavaScript's everything-is-async, single threaded model was that it was just slightly less difficult to reason about than multiple threads and shared state. (Though I'd say that's debatable...) My guess is that, despite the sugar coating that JavaScript's async internals have received of late, writing stable multi-threaded code with JavaScript is going to be hard. JavaScript now has the safety of multi-threaded code with the ease of asynchronicity!
- AgentME 10y agoSharedArrayBuffer only allows plain typed (byte) arrays to be shared at least. Arbitrary javascript objects can't be shared, so there's a very clear division about what can get affected by other threads and what can't. You don't have to worry about whether existing libraries are thread-safe, etc.
- Klathmon 10y agoNot only that, but if you don't need "Shared" array buffers (meaning more than one thread using it at once) you can use "Transferrable" [1] ArrayBuffers. It's just a zero-copy transfer to a worker (or from a worker) but it makes sure the "sender" doesn't have access to the memory any more. It's incredibly easy to use, avoids all the common issues and pitfalls with shared memory, and being zero-copy it's stupidly fast. Obviously it's not a replacement for true shared memory, but i've used it in the past to do some image processing in the browser (broke the image into chunks, and transferred each chunk to a worker to process, then return and stitch them all back together). [1]https://developer.mozilla.org/en-US/docs/Web/API/Transferable https://developer.mozilla.org/en-US/docs/Web/API/Transferabl...
- pfooti 10y agoThat's pretty rad - the vast majority of what I would see myself wanting to do in a multithreaded javascript world would be limited to something with transferrable arraybuffers. Like: "hey, worker, go do some work and lmk when you're done". Moving big chunks of memory around in ways that atomically only ever have one allowed accessing thread would be plenty.
- CHsurfer 10y agoI keep hoping that JS would evolve to support the actor model, a la Erlang/Elixir, with their process based persistence, concurrency via message passing, etc. It just seems so much simpler and tractable than this proposal.
- coldtea 10y agoThat wouldn't do much for the use cases they want to use it (multimedia, games, number-crunching etc as in the example in TFA)
- lennelpennel 10y agoIn some ways web workers feel a bit like actors. granted a poor man's actor.
- cpeterso 10y agoI've seen projects to compile Erlang to JS, but has anyone experimented with a JS compiler that targets Erlang's BEAM VM like Elixir? JS is an approachable language but Node has problems with scaling and error handling of non-blocking IO. Erlang solves those problems but the language is not approachable and has a smaller ecosystem than JS. I'm imagining something like Node with "micro-workers" so developers could reuse their existing JS code, but not have to worry about scaling or non-blocking APIs.
- jchrisa 10y agoPlease implement!
- bhauer 10y agoOn my grossly overpowered workstation, I can only crank the number of workers in the Mandelbrot demo to 20 [1]. Attempting to go beyond 20, the console reports: RangeError: out-of-range index for atomic access That said, 20 workers is about 11x faster than the single-threaded version. [1] https://axis-of-eval.org/blog/mandel3.html?numWorkers=20 https://axis-of-eval.org/blog/mandel3.html?numWorkers=20
- cpeterso 10y agoAre JavaScript workers implemented using real OS threads or green threads? How heavyweight is a worker?
- Klathmon 10y agoThey are real OS threads in all implementations i've seen. As for how heavy, they are definitely a bit heavier than i'd like. But rather than me try to describe it, [1] is a really good benchmark with results that you can run yourself if you want. [1]https://github.com/gmarty/web-workers-benchmark https://github.com/gmarty/web-workers-benchmark
- hkjgkjy 10y agoIf only we did not have mutable data structures, there would be no or few problems to find in this. Concurrency isn't hard - try Clojure core/async and you will find out. Shared mutable state is mind-boggingly hard
- schmichael 10y ago> if we want JS applications on the web to continue to be viable alternatives to native applications on each platform This is where I disagree with the direction Mozilla has been going for years. I don't want the web to be a desktop app replacement with HTTP as the delivery mechanism. I'm fine with rich single page web apps, but I don't understand the reason why web apps need complete feature parity with desktop apps. Why not let the web be good at some things and native apps be good at others?
- yoklov 10y agoOne reason might be that native app distribution platforms are getting progressively more closed, whereas the web is getting/remaining open.
- schmichael 10y agoClosed has benefits. "Curated" is a nice euphemism for closed. It's much easier to childproof a curated app store than The WWW for example. I'm not saying closed is better -- they're just different and that's ok. In fact I like how different they are. It means each has its own unique strengths and doesn't have to worry about trying to do it all.
- yoklov 10y agoIMO what you want are curated views into open platforms. Some arbiter deciding what is/isn't acceptable for the platform is very far from ideal. Consider all the great games that have been prevented from going on iOS. Admittedly, something like this seems difficult to do for the web.
- dottrap 10y agoI might get downvoted for this, but I think it is an important point to really consider. The claim that the web is getting/remaining open is somewhat dubious. As JavaScript and web browsers get increasingly complex, it is harder for anybody to just start up and write a usable, compliant web browser from scratch, which in fact entrenches the status quo. And why do we simply trust the existing browsers? Google has very specific goals to monetize you and Chrome can be leveraged to help that goal. Microsoft's historic fight with the web and now their current changing business goals are a reminder that their web browser goals can always change, and their current model seems more like Google. Apple is always Apple. And why should we blindly trust Mozilla? They depend on external funding to keep the foundation going to pay for a lot of the complex engineering that goes into Firefox. I'm not accusing them of anything wrong, but you can look up prior controversies about their funding sources and decisions and see people don't agree it is all rosy. I'm suggesting the increasing technical complexity is not necessarily working towards the goal of an open web because it is entrenching the gatekeepers that can make the web browsers.
- _getify 10y agoI'm excited about the `SharedArrayBuffer` addition, but quite meh on the `Atomic.wait()` and `Atomic.wake()`. I think CSP's channel-based message control is a far better fit here, especially since CSP can quite naturally be modeled inside generators and thus have only local-blocking. That means the silliness of "the main thread of a web page is not allowed to call Atomics.wait" becomes moot, because the main thread can do `yield CSP.take(..)` and not block the main UI thread, but still simply locally wait for an atomic operation to hand it data at completion. I already have a project that implements a bridge for CSP semantics from main UI thread to other threads, including adapters for web workers, remote web socket servers, node processes, etc: https://github.com/getify/remote-csp-channel https://github.com/getify/remote-csp-channel What's exciting, for the web workers part in particular, is the ability to wire in SharedArrayBuffer so the data interchange across those boundaries is extremely cheap, while still maintaining the CSP take/put semantics for atomic-operation control.
- rl3 10y ago>Consider synchronization: The new Atomics object has two methods, wait and wake, which can be used to send a signal from one worker to another: one worker waits for a signal by calling Atomics.wait, and the other worker sends that signal using Atomics.wake. Having not yet played with this myself: is anyone familiar with what kind of latency overhead is involved with signaling in the Atomics API? I'm not very familiar with the API yet, so I've no idea how signaling is implemented under the hood. The MessageChannel API by contrast (i.e. postMessage) can be quite slow, depending. While you can use it within a render loop, it usually pays to be very sparing with it. Typical latency for a virtually empty postMessage call on an already-established channel is usually .05ms to .1ms. Most serialization operations will usually balloon that to well over 1ms (hence the need for shared memory). Plus transferables suck. >Finally, there is clutter that stems from shared memory being a flat array of integer values; more complicated data structures in shared memory must be managed manually. This is probably the biggest drawback to the API, at least for plain Javascript. It really favors asm.js or WebAssembly compile targets for seamless operation, whereas plain Javascript can't even share native types without serialization/deserialization operations to and from byte arrays.
- imaginenore 10y agoI really want WebCL. Worker threads are just so lame compared to what GPUs can do.
- piotrkaminski 10y agoIf the problem that this is trying to solve is that `postMessage` is slow and you can't transfer slices of arrays, then perhaps they should solve it by speeding up `postMessage` and making array slicing cheap? Forcing a shared-memory concurrency model into JavaScript seems like a bit of an overreaction.