Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSPI scheduler #4789

Open
pulsejet opened this issue Mar 9, 2025 · 5 comments
Open

JSPI scheduler #4789

pulsejet opened this issue Mar 9, 2025 · 5 comments
Labels
enhancement New feature or request wasm WebAssembly

Comments

@pulsejet
Copy link

pulsejet commented Mar 9, 2025

(This may end up being more of a thought experiment, please feel free to close this issue)

JSPI is supposed to be the spiritual successor to asyncify, which tinygo currently uses for scheduling on GOOS=JS. At a high level (from my understanding) JSPI essentially provides some form of constrained stack switching (e.g. cannot suspend JS frames).

Out of curiosity and with my (very) limited knowledge of how tinygo or JSPI works, I took a shot at this and got some a basic Go program with goroutines to work without asyncify on Chrome. In my implementation,

  1. Each goroutine is a separate stack
  2. Pause suspends the stack and puts the promise in a global map
  3. Resume suspends the current stack and resolves the promise, reverting back to the old goroutine
  4. After suspending the stack, the scheduler is invoked directly. If there is no more work, a trap gets rid of the stack.

If anyone is curious - here's where I stopped
pulsejet@28c1d8d

I think (with my limited knowledge) it's hard to say which approach is faster (unwind-rewind, or a JS call for each scheduler event), so it might make sense to run some benchmarks first.

As the first line says, please close if this is a stupid idea.

@aykevl
Copy link
Member

aykevl commented Mar 10, 2025

Very interesting! And probably something we'll want to have eventually.

Unfortunately JavaScript Promise Integration isn't fully supported in any browser yet. To be able to support this feature, we'd want to be able to run tests in CI so that probably means we'd need at least Node.js support.

@deadprogram deadprogram added enhancement New feature or request wasm WebAssembly labels Mar 12, 2025
@paralin
Copy link
Contributor

paralin commented Mar 18, 2025

Jspi announcement, jspi spec, jspi origin trial - WebAssembly.Suspending is not implemented in Chrome or Firefox as of 03/12/2025, but it is in an Origin Trial in Chrome.

Looking at the timeline, WASIp3 is expected to be released "later this year" (2025), with release candidate snapshots available in the "next couple of months" and experimental runtime support landing in tools like Spin shortly after.

https://www.fermyon.com/blog/looking-ahead-to-wasip3

The latest update on jspi can be found in the extent to extend experiment
email on the Blink mailing list in which, as of January 29, 2025:

SPI has been inherently hard to specify, and validate security requirements
for given that it is somewhat sandwiched between JS & Wasm. Concretely, since
the last OT extension, the late breaking changes have been merged into the
specification and we've gotten more signals about the exploitable security
surface of JSPI (OT features are treated as shipped features for V8), and we'd
like to focus on hardening security ahead of an intent to ship.

~ Deepti Gandluri

@pulsejet
Copy link
Author

I want to add a major caveat I discovered later. It seems like the engine would maintain a full wasm stack for each goroutine in this model, which is large-ish (984kB from my understanding), so starting up a lot of goroutines would likely oom quickly.

@paralin
Copy link
Contributor

paralin commented Mar 18, 2025

I am working on a prototype for async calls using Atomic.wait and two cooporating js agent contexts (two WebWorker or SharedWorker for example) as a stop-gap until jspi is complete, see here

@pulsejet
Copy link
Author

I am working on a prototype for async calls using Atomic.wait and two cooporating js agent contexts (two WebWorker or SharedWorker for example) as a stop-gap until jspi is complete, see here

This is also how WASMFS works currently when JSPI isn't available. But you still need to unwind and rewind the stack to switch between goroutines in this design. This does help with the case where you've only one goroutine, no need to unwind that then 👍🏻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request wasm WebAssembly
Projects
None yet
Development

No branches or pull requests

4 participants