We would like to propose Tasklets – an API to make it easier for developers to move work off the main thread/UI thread.
Jank remains a problem. While making a lot of APIs asynchronous by default helped, some work is inherently atomic. iOS, Android and other native platforms are very strict about the usage of any APIs not critical to UI manipulation on the main thread. The web seems to be the odd one out. WebWorkers already allow developers to move work to another thread, but are rather expensive and clunky to use with only postMessage() as a means of communication.
Tasklets would allow developers to move work to another thread in a very ergonomic way. As the name suggests, a Tasklet is a Worklet that runs user code. This means it is more lightweight than a WebWorker. Also, a single OS thread could be shared between multiple tasklets, making it feasible to use on memory-restricted mobile devices as well.
Please take a look at the explainer above for usage, syntax and more details.
@iank, @dknox and myself will be happy to answer any questions you might have.
I guess the best thing I can do is refer you to the official Worklet spec from Houdini. A tasklet is a special worklet. The gist is that a single OS thread can host multiple worklets (from different origins, too!) and they have different lifetime constraints.
Since this is a promise based API, it means that the Tasklet’s role is limited to running functions on the main thread’s behalf. Have you considered how a Tasklet might initiate communication? For example, if the Tasklet was performing expensive calculations periodically, how could it send data back to the main thread?
Ah, ok, I was wondering what the EventTarget stuff was about. Ok, that makes sense then. Side note, the ability to extend EventTarget would be great to have in the main thread as well.
Going back to the perf considerations of worklets, the spec says that they have a limited global scope. Is the scope defined by each subtype of worklet, meaning will Tasklet define its global scope? If so, what things will be left out?
Yes, each subtype defines what is exposed in their scope. We haven’t figured it out in detail (there’s only a short passage in the explainer), but as a rule thumb for now: “If it’s synchronous, the API is not exposed in Tasklets”.
Other than that we’d like to make tasklets as divers and generically applicable as possible.
The main reason this is designed as a worklet and not a worker is so that tasklets from different origins can potentially share a single OS thread on mobile devices. To avoid one tasklet starving out others, we still want to strongly encourage mostly asynchronous work.
Yes, doSomeExpensiveProcessing() was supposed to be a block of synchronous work to show that in a tasklet it is “okay” to have these bigger chunks of synchronous work, as they don’t block rendering, but developers still need to be mindful.
What’s important to me is that bad APIs are blacklisted rather than good APIs be whitelisted. If this API goes through I’m assuming that would essentially deprecate Web Workers, so Tasklets need to be at least as powerful. It’s already a problem that Workers are often forgotten about (ex. FormData not being supported in Safari workers). But it sounds like you’re taking the right approach here, so I’m happy.