Skip to content

Instantly share code, notes, and snippets.

@justinfagnani
Created October 18, 2018 19:57
Show Gist options
  • Save justinfagnani/43a1ae9af8c12c081048d49b4f0a25ee to your computer and use it in GitHub Desktop.
Save justinfagnani/43a1ae9af8c12c081048d49b4f0a25ee to your computer and use it in GitHub Desktop.
Preemptible JavaScript Functions

Preemptible JavaScript Functions

Can we allow JS functions to opt-in to be prempted?

Synchronous

An expensive synchronous function will jank the UI:

function expensive() {}

function responseToInput() {
  expensive(); // jank
}

Cooperative

A cooperatively scheduled task can yield to try to not jank the main thread, but it has to yield often enough so that work fits in the frame budget. If a cooperatively scheduled task calls out to an expensive synchronous function, it'll still cause jank.

async function expensive(context) {
  for (...) {
    await context.yield();
    await somethingElse(context);
  }
}

function respondToInput() {
  await scheduler.schedule(expensive); // jank
}

Premptive

What if we could allow functions to opt-in to being preempted?

The function would still run on the main thread and have synchronous DOM access, but it could be preempted to respond to user input, animate/layout/paint, etc., based on the UA's scheduling.

function premptable expensive() {
  for (...) {
   window.foo = 123
   div.id = "foo"
    
    assert(div.id === "foo")
  }
}

function respondToInput() {
  await preempt expensive(); // no jank?
}

Preemptible functions and everything they call would have to be compiled with safe points that can yield. Java's green threads added these to the beginning of every block and loop. pthreads have a pthread_suspend function, but it appears to not be widely implemented.

This might not work well at all. Assumptions about state not being mutated by other code without having yielded no longer hold. It might be the case that preemptible functions need to be tied to some isolated DOM to have any hope of being reliable. A preemptible JS realm associated with a closed ShadowRoot might work.

Background

WebKit's Concurrent JavaScript experiment: https://webkit.org/blog/7846/concurrent-javascript-it-can-work/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment