6 ms·
I think it's a very strong point that moving script code off the main thread can help achieve smooth UIs. No more GC pauses, no more slowdowns if the JS engine
by azakai 12y ago
I think it's a very strong point that moving script code off the main thread can help achieve smooth UIs. No more GC pauses, no more slowdowns if the JS engine hits a snag, etc.
I think this is actually possible on the web as well. Someone could write a UI framework which runs JS in a Worker, and sends messages to the main thread, on which there is HTML and minimal JS to receive the messages and handle them.
I'm surprised this hasn't been done, or has it and I just haven't heard about it?
If you're worried about the overhead of transferring lots of messages from the Worker to the main thread, I think it can be pretty fast actually. I did an experiment with proxying WebGL that way, which is a fairly high-traffic API, with nice results,
https://blog.mozilla.org/research/2014/07/22/webgl-in-web-workers-today-and-faster-than-expected/ https://blog.mozilla.org/research/2014/07/22/webgl-in-web-wo...
For something rendering a UI, message passing overhead should be reasonable, especially if the framework is smart enough to only send over what changes (like React Native does).
- untog 12y agoIIRC, Web Workers have a really limited subset of functionality available to them, which adds a whole load of gotchas to anything like this.
- azakai 12y agoIt is somewhat limited, but using message passing to the main thread, you can render a UI or even use WebGL or Web Audio or anything else. See the link for an example with WebGL.
- untog 12y agoOh, I know. But it's rare that a webapp does things computational enough that it's worth the extra overhead - most lagginess is actually at the UI level, in my experience (and why virtual DOMs are so popular now). I've seen Web Workers used in things like graphing libraries, though.
- aikah 12y agoIs playcanvas using emscriptem or is it written directly in js? nice project by the way. Also what does the worker do? does it have access to the canvas context or it just does some calculations and communicate with the main thread via serialized data.
- azakai 12y agoPlaycanvas is written directly in JS, but does use an emscripten-compiled physics engine (bullet/ammo). Serialized data. Workers currently can't have access to canvas contexts.
- jordwalke 12y agoWe did a bunch of experiments with running React in a web worker. Maybe we should revive them. Because it's React, it ends up being easy and is basically the same setup (serialized events etc) as what React Native does.
- nwienert 12y agoWhy wasn't this explored more before going full out with React Native? I feel like this would be smart to compare the two: web + webworkers vs native. There was a lot of hype about hybrid apps "sucking", but I bet it doesn't once you get off the thread.
- jordwalke 12y agoTrust me, we tried. But as long as image decoding blocks the main thread (Webkit), you are helpless to update the UI thread at a fast pace. We even tried decoding images in a web worker and sending the result back to the main thread - but decoding in JS is very slow so general application throughput suffers (not through fault of JS itself, but because JS lacks SIMD which image decoding algorithms use in order to decode images quickly). But running React in a web worker is still a really great idea. There would just be a lot of little edge cases to handle (like when you click a link - you need to prevent default of navigation, then send that link click to the web worker to see if your app wants to prevent default, if not, force the redirect back on the main thread). Having tight control over text editing might be challenging as well. These are difficulties, but I suspect they are a fixed set of challenges that are worth the increased parallelism in an increasingly multicore world. But are web workers currently The Solution To All Our Mobile App Needs? No, but they're a great tool that are highly underutilized by JS developers, and that React is uniquely positioned to take advantage of.
- Touche 12y agoAs for events, have the worker send which events it is interested in rather than the reverse as you suggest.
- jlongster 12y agoYou are speaking my language! I would love to see a prototype of this. I've been thinking about it since I saw React Native. I wonder if there's even value in something like an asm.js-compiled layout system, which absolutely positions elements. One of the insights of React Native is that to build apps, we really only need a small subset of the web's layout algorithms. Only flexbox, really. So if we recognize this subset, and remove everything else, there main thread can focus on really smooth performance. React Native even performs the flexbox layout on a 3rd thread, and tells the main thread where to absolutely position stuff. Obviously we want to re-use as much of HTML as we can, but there might be some crazy ways to remove stuff from the main thread. EDIT: It should be noted that Mercury, a React-inspired library (https://github.com/Raynos/mercury https://github.com/Raynos/mercury), has examples of running in a web worker. It is pretty cool, but I think it needs to be fleshed out more.
- nwienert 12y agoMe me! I'll be exploring this soon and I'm sure I'll reach out for help before I get too far. Could do a lot of stuff off thread, from data to layout calcs. My profile should have some info related to the hybrid stuff.
- jlongster 12y agoVery cool! I'll keep an eye on your work!
- azakai 12y agoMe too. I'd love to chat more about this with both of you, this seems like a direction definitely worth exploring. Maybe we could set up a github project for it? Or talk in an issue on your existing repo, nwienert?
- nwienert 12y agoI'd like to see a github repo. You can hit me up on twitter, info in my profile. I think even just finding the right library to make using webworkers + npm + webpack would be great to start, because honestly its all the other stuff that slows down the thread. React can run on the main thread for the most part. Some reading: https://news.ycombinator.com/item?id=6982485 https://news.ycombinator.com/item?id=6982485 http://stackoverflow.com/questions/18056922/is-there-a-way-to-create-out-of-dom-elements-in-web-worker http://stackoverflow.com/questions/18056922/is-there-a-way-t... Edit: webpack + webwoker: https://github.com/webpack/webpack/tree/master/examples/web-worker https://github.com/webpack/webpack/tree/master/examples/web-...
- johnpmayer 12y agoRegarding moving script code off the main thread: I wrote a cooperative FRP engine that multiplexes signal graph update recalculation onto Web Workers. UI updates like virtual DOM would live on the main thread. https://github.com/Johnpmayer/liquid-thorium https://github.com/Johnpmayer/liquid-thorium
- rdtsc 12y ago> I'm surprised this hasn't been done, or has it and I just haven't heard about it? N2O framework might do that. https://github.com/5HT/n2o https://github.com/5HT/n2o Book: https://synrc.com/apps/n2o/doc/book.pdf https://synrc.com/apps/n2o/doc/book.pdf One pattern you can do is send events to the server, server renders data asynchronously (maintains state for each client in a lightweight process), then ships result back to client via websocket binary frames. You also decide how much rendering happens where. Can even do whole HTML elements on the server if you want.
- akrymski 12y agoI've been thinking about this as well yesterday, but to be honest I'm not sure where the benefits are. In theory the browser is doing the rendering in a separate thread anyway, i.e. CSS layout and things like scrolling are handled by the browser. If you're doing a long algorithmic (CPU-intensive) computation in JS then you should probably do that in a WebWorker anyway. Otherwise I'm not sure the overhead is worth it, for example the dragging / touch events should be invoking such a tiny amount of javascript that you shouldn't see much benefit in moving that logic to a separate thread. Would be interested to see real examples of where this is makes sense. Disclosure: we're developing an email client using Cordova and purely web tech using our own framework: https://github.com/techlayer/espresso.js https://github.com/techlayer/espresso.js
- nwienert 12y agoExactly. I think moving everything but React into the web worker is enough. But that itself isn't easy as far as my limited knowledge, you need to have separate script files. Perhaps a webpack plugin that manages that for you?
- akrymski 12y agoI think simply moving any function that takes more than 10ms to a web worker is enough frankly.
- larsberg 12y ago> I think it's a very strong point that moving script code off the main thread can help achieve smooth UIs. What, you mean like we do in Servo? https://github.com/servo/servo https://github.com/servo/servo :-) Our main thread (if you can call it that) just does compositing and handles dispatching UI events. Script, layout, resource loading, and the rest run concurrently in background threads.
- jlongster 12y agoThat's amazing. I hadn't even though about Servo in light of all of this. In current browsers, JavaScript runs in the same thread as the UI, right? In Servo, how do you do interaction with the DOM like `clientHeight`? It just pauses the entire JS engine while it goes and talks to the UI thread? Maybe we should be thinking of all of this in terms that map well to Servo's current architecture. EDIT: What's really exciting about Servo is that hopefully the architecture's parallelism is really sound, even if certain properties of the current web restrain it. Then we can work on ways to remove those properties, and in Servo it's a simple switch to turn on more and more parallelism.
- pcwalton 12y ago> In Servo, how do you do interaction with the DOM like `clientHeight`? It just pauses the entire JS engine while it goes and talks to the UI thread? Yes, but we'd like to experiment with new APIs in the future like `getBoundingClientRectAsync()` that will allow pages to do that kind of thing asynchronously.
- jordwalke 12y agoI'm also interested in Servo as well. With React Native, we had the liberty to restrict certain paradigms that don't map well to building a parallelizable pipeline of operations. So the JS thread can't synchronously query for layout, which happens in the next stage, and the layout stage can't synchronously block on reading main thread (UIKit etc) values. By restricting what the programmer can do, it naturally formed a pipeline where layout can be performed in the second stage while JS is determining the next UI update and so on. I'm not sure the extent to which this benefits us right now, but even mobile devices are beginning to have four cores so it seems like a nice property to maintain as long as it doesn't cause problems. Servo sounds cool, and I'm curious how it takes advantage of a similar architecture but while the programmer has free reign to "clog the pipeline" by synchronous queries on layout etc. I'm sure they've thought of it, I'd just like to hear what they came up with.
- pchristensen 12y agoPedestal Client from Cognitect did this - see https://github.com/pedestal/app-tutorial/wiki/Parallel-Processing https://github.com/pedestal/app-tutorial/wiki/Parallel-Proce... and my notes at http://pchristensen.com/blog/articles/pedestal-tutorial-part-2-notes/ http://pchristensen.com/blog/articles/pedestal-tutorial-part... (under "Parallel Processing"). Too bad they stopped working on it.
- seanmcdirmid 12y agoSomeday you'd think they might just go ahead and add multi-threading, shared memory to Javascript? It is definitely a can of worms, but the current web worker situation is just not workable for many use cases. WPF has a UI and a separate closed off rendering thread, which works quite well performance wise.
- haberman 12y ago> I think it's a very strong point that moving script code off the main thread can help achieve smooth UIs. No more GC pauses, no more slowdowns if the JS engine hits a snag, etc. BeOS took UI multithreading farther than any other environment I've ever used. And it paid off: I still think it might be the case that BeOS on circa 2000 hardware was more consistently responsive than any environment I have used before or since. More technical detail about BeOS's multithreaded UI design: http://arstechnica.com/civis/viewtopic.php?p=17348543&sid=e2925e09265cf8a3a0cab8347f5cc2e0#p17348543 http://arstechnica.com/civis/viewtopic.php?p=17348543&sid=e2...