Live data from Hacker News

The Path to Parallel JavaScript

blog.mozilla.org

41–50 of 58 posts

Re: The Path to Parallel JavaScript

#41

This is nice for some pretty limited use cases, but the most common use case for multithreading in app-like programs (which is what Worker-based apps presumably service: these are not documents) is removing latency from the UI thread. But as long as only the main thread can touch the UI, and the main thread also can't access shared memory, this limits uses of this to scenarios where copying the entire render state fr…

The blog post does mention the main thread, as something that is more complex and in need of further investigation.

Still, even without shared memory being accessible to the main thread, I think sharing between workers can be extremely useful. Yes, you need to proxy information to the main thread in order to render, but that doesn't need to be a big problem. See for example the test here, where a 3D game's rendering was proxied to the main thread, with little loss of performance,

https://blog.mozilla.org/research/2014/07/22/webgl-in-web-wo...

That very small overhead could be worth letting the game run in multiple workers while using shared memory.

Also, things like Canvas 2D and WebGL are APIs that might exist in workers, there are efforts towards that happening right now. That would eliminate the need to copy anything to the main thread, and avoid a lot of latency.

Re: The Path to Parallel JavaScript

#43
post #41

This is nice for some pretty limited use cases, but the most common use case for multithreading in app-like programs (which is what Worker-based apps presumably service: these are not documents) is removing latency from the UI thread. But as long as only the main thread can touch the UI, and the main thread also can't access shared memory, this limits uses of this to scenarios where copying the entire render state fr…

The blog post does mention the main thread, as something that is more complex and in need of further investigation. Still, even without shared memory being accessible to the main thread, I think sharing between workers can be extremely useful. Yes, you need to proxy information to the main thread in order to render, but that doesn't need to be a big problem. See for example the test here, where a 3D game's rendering…

I can't speak to the BananaBread codebase, since I haven't read it — although BananaBread performs poorly as compared to commercial engines, regardless — but if you look at even the published benchmarks in that blog post, the Worker-based implementation is slower in all cases except for Firefox with two bots. Chrome is always slower when using Workers, sometimes massively so, and Firefox with ten bots is slower multithreaded than single-threaded.

Regardless, shared memory isn't only useful for WebGL. It's useful for any kind of UI where you don't want to block the main thread, and if you don't have DOM access it's tough to make that work. If copying is fine then current Workers are good enough; if copying isn't fine, then this doesn't change that.

Re: The Path to Parallel JavaScript

#44
post #41

Earlier quoted context omitted.

The blog post does mention the main thread, as something that is more complex and in need of further investigation. Still, even without shared memory being accessible to the main thread, I think sharing between workers can be extremely useful. Yes, you need to proxy information to the main thread in order to render, but that doesn't need to be a big problem. See for example the test here, where a 3D game's rendering…

I can't speak to the BananaBread codebase, since I haven't read it — although BananaBread performs poorly as compared to commercial engines, regardless — but if you look at even the published benchmarks in that blog post, the Worker-based implementation is slower in all cases except for Firefox with two bots. Chrome is always slower when using Workers, sometimes massively so, and Firefox with ten bots is slower multi…

I agree with

> If copying is fine then current Workers are good enough; if copying isn't fine, then this doesn't change that.

I am saying that copying is fine (for most apps).

Copying is fine because BananaBread is indeed less performant than commercial engines, as you said, and that actually makes it a better test candidate here. It does far more GL commands than a perfectly optimized engine would, which means much more overhead in terms of sending messages to the main thread.

Despite that extra overhead, it does very well. 2 bots, a realistic workload, is fast in Firefox, and the slowdown in Chrome (where message-passing overhead is higher) is almost negligible. 10 bots, as mentioned in the blogpost, is a stress test, not a realistic workload. As expected, things start to get slower there. (Game is still playable though!)

And large amounts of GL commands, as tested there, are much more than what a typical UI application would need. So for UI applications, that just want to not stall the main thread, I think a single worker proxying operations to the main thread could be enough. Copying is fine.

The proposal in the blogpost here is for other cases. Workers + copying already solve quite a lot, very well. What this new proposal focuses on are computation-intensive applications, that can multiply their performance by using multiple threads. For example, an online photo-editing application needs this. This might be just a small fraction of websites, but they are important too.

Re: The Path to Parallel JavaScript

#45

This is nice for some pretty limited use cases, but the most common use case for multithreading in app-like programs (which is what Worker-based apps presumably service: these are not documents) is removing latency from the UI thread. But as long as only the main thread can touch the UI, and the main thread also can't access shared memory, this limits uses of this to scenarios where copying the entire render state fr…

I'm of the opinion that adding "proper" (read: low-level) multithreading is a bad idea for Javascript.

How will it interact with the existing event loop? How will scheduling work? How about sharing state properly? Is my work going to crash because some bozo writes a jQuery plugin for background processing that doesn't understand how spinning on a mutex can cause trouble?

Javascript developers generally lack, due to the language and the environment, any sort of empathy for what is and is not a good idea in a place where concurrent modification of shared state is possible.

Web workers, wisely, solved this problem by creating explicit messaging. This gets you most of the way there without running into the really nasty bugs you see in native code.

Adding a shared buffer object as proposed (presumably giving an interleaved set of views onto the same underlyling backing array, much as we do with typed buffers) could be acceptable, because you can guarantee isolated access to elements.

However, adding the more general threading support you see in, for example, C++ would be a nightmare. I'm already a little wary of the maintenance and legacy costs that ES6 are going to impose on us...giving devs the power to do dumb shit with threads isn't going to help our industry.

Re: The Path to Parallel JavaScript

#46

This is nice for some pretty limited use cases, but the most common use case for multithreading in app-like programs (which is what Worker-based apps presumably service: these are not documents) is removing latency from the UI thread. But as long as only the main thread can touch the UI, and the main thread also can't access shared memory, this limits uses of this to scenarios where copying the entire render state fr…

I'm of the opinion that adding "proper" (read: low-level) multithreading is a bad idea for Javascript. How will it interact with the existing event loop? How will scheduling work? How about sharing state properly? Is my work going to crash because some bozo writes a jQuery plugin for background processing that doesn't understand how spinning on a mutex can cause trouble? Javascript developers generally lack, due to t…

An addendum.

I think that adding full support for things like Canvas and WebGL rendering would relieve the majority of the remaining issues people have, if done alongside that shared buffers approach.

Hell, written in a functional style Javascript looks none too different from, say, PLINQ, and if they decide to add library-level function parallelism I could absolutely get behind it.

Just save us from copy-and-pasted $.raiseSemaphore() and $.joinOnMonitor()--and history shows us, that is what we'll be expecting.

EDIT:

One more thing...JS does not lend itself to static analysis, and that may make writing safe parallel code even more difficult.

Re: The Path to Parallel JavaScript

#47

Why not implement go routines model?

Aren't go routines pretty similar to WebWorkers, but with special syntax for creating them (and sending/receiving messages over channels) and perhaps lighter weight (though that may just be an implementation issue with current JS engines)?

Edit: nevermind, it looks like go routines can share memory, (but channels are the preferred method of synchronization): https://golang.org/ref/mem

Re: The Path to Parallel JavaScript

#48
post #44

Earlier quoted context omitted.

I can't speak to the BananaBread codebase, since I haven't read it — although BananaBread performs poorly as compared to commercial engines, regardless — but if you look at even the published benchmarks in that blog post, the Worker-based implementation is slower in all cases except for Firefox with two bots. Chrome is always slower when using Workers, sometimes massively so, and Firefox with ten bots is slower multi…

I agree with > If copying is fine then current Workers are good enough; if copying isn't fine, then this doesn't change that. I am saying that copying is fine (for most apps). Copying is fine because BananaBread is indeed less performant than commercial engines, as you said, and that actually makes it a better test candidate here. It does far more GL commands than a perfectly optimized engine would, which means much…

Here are some things that BananaBread doesn't test that I suspect would break larger games in commercial engines:

* High-poly models. This is one area where copying breaks down: that can be a ton of data. BananaBread has a single, low-poly model that it uses for NPCs, and it presumably rarely (if ever?) needs to be re-copied.

* Large, seamless worlds. If you can transfer the entire world into a single static GL buffer, sure, copying isn't a problem since it only happens once on boot. If you need to incrementally load and unload in chunks, you're going to be paying that cost again and again.

* Multi-pass rendering. In fact, the proxying approach makes multi-pass rendering impossible, as noted in the blog post.

By all means, if your application already works single-threaded, or within the confines of the existing spec, you're going to be fine. But memory copies aren't free, and UI offloading is one of the biggest reasons to use shared memory.

Shared memory in Workers is nice — it doesn't make anything worse, and it makes some things better! — but it's a little disappointing that the main thread can't access the shared memory buffers. That's all.

Re: The Path to Parallel JavaScript

#49
post #44

Earlier quoted context omitted.

I agree with > If copying is fine then current Workers are good enough; if copying isn't fine, then this doesn't change that. I am saying that copying is fine (for most apps). Copying is fine because BananaBread is indeed less performant than commercial engines, as you said, and that actually makes it a better test candidate here. It does far more GL commands than a perfectly optimized engine would, which means much…

Here are some things that BananaBread doesn't test that I suspect would break larger games in commercial engines: * High-poly models. This is one area where copying breaks down: that can be a ton of data. BananaBread has a single, low-poly model that it uses for NPCs, and it presumably rarely (if ever?) needs to be re-copied. * Large, seamless worlds. If you can transfer the entire world into a single static GL buffe…

I understand your disappointment, clearly more opportunities are opened up on the main thread. As the article says, this is a proposed first step, and the main thread is trickier, so it can be considered carefully later on. Meanwhile, for a large set of use cases, the current proposal can provide massive speedups.

Re: The Path to Parallel JavaScript

#50
post #41

Earlier quoted context omitted.

The blog post does mention the main thread, as something that is more complex and in need of further investigation. Still, even without shared memory being accessible to the main thread, I think sharing between workers can be extremely useful. Yes, you need to proxy information to the main thread in order to render, but that doesn't need to be a big problem. See for example the test here, where a 3D game's rendering…

I can't speak to the BananaBread codebase, since I haven't read it — although BananaBread performs poorly as compared to commercial engines, regardless — but if you look at even the published benchmarks in that blog post, the Worker-based implementation is slower in all cases except for Firefox with two bots. Chrome is always slower when using Workers, sometimes massively so, and Firefox with ten bots is slower multi…

> if copying isn't fine, then this doesn't change that.

Good point. I imagine it would be possible to transfer ownership of a SharedArrayBuffer to the main thread from a worker, just as it is done today with zero-copy transferable ArrayBuffers.

References to the SharedArrayBuffer in all workers would be made unusable. When the code on the main thread is done it can transfer ownership of the SharedArrayBuffer back to the workers.

Post reply on HN