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

There should be a way to abort wasm compilation #1262

Open
chicoxyzzy opened this issue Jan 31, 2019 · 12 comments
Open

There should be a way to abort wasm compilation #1262

chicoxyzzy opened this issue Jan 31, 2019 · 12 comments

Comments

@chicoxyzzy
Copy link
Member

chicoxyzzy commented Jan 31, 2019

Compilation (and instantiation?) of WebAssembly module could be a resource intensive operation so there should be a way for wasm hosts to abort this step in cases when module is not needed anymore for some reasons.
As for JS hosts, theoretically cancellation methods should be in JS API, but JS doesn't have cancellation mechanism for promises yet. There are AbortController and AbortSignal which are used to abort Fetch. Probably they can be used to abort wasm compilation (passing signal as extra parameter to WebAssembly.compile), but they are part of DOM WHATWG spec, so it's only possible to use them in browsers and as a consequence only in Web API.

@xtuc
Copy link

xtuc commented Jan 31, 2019

Note that Promise and Fetch run on the main thread, whereas Wasm compilation (if asynchronous) can be done in background, only the instantiation is blocking.

Also I'm wondering what happens when an module (while compiling) gets garbage collected.

@chicoxyzzy
Copy link
Member Author

chicoxyzzy commented Jan 31, 2019

whereas Wasm compilation (if asynchronous) can be done in background

Yes, but the problem is not main thread blocking, but unnecessary operations (fetch also doesn't block main thread). Also it's related to any host, not just browsers.

@chicoxyzzy
Copy link
Member Author

Also I'm wondering what happens when an module (while compiling) gets garbage collected.

Good question. I think we can test this case aborting fetch while instantiateStreaming / compileStreaming.

@lars-t-hansen
Copy link
Contributor

Also I'm wondering what happens when an module (while compiling) gets garbage collected.

In Firefox the JS WasmModule object is a front for an internal Module object which is shared among the threads that have a handle to the module; the object is (atomically) refcounted. When the JS WasmModule object is GC'd it just drops its refcount on the Module, but any ongoing background compilation has a reference to the Module object and will keep it alive until the compilation is finished.

@xtuc
Copy link

xtuc commented Jan 31, 2019

but any ongoing background compilation has a reference to the Module object and will keep it alive until the compilation is finished

Is there any plan to stop the compilation in that case? I don't know how common that situation will be.

@backes
Copy link
Member

backes commented Jan 31, 2019

Also I'm wondering what happens when an module (while compiling) gets garbage collected.

In Firefox the JS WasmModule object is a front for an internal Module object which is shared among the threads that have a handle to the module; the object is (atomically) refcounted. When the JS WasmModule object is GC'd it just drops its refcount on the Module, but any ongoing background compilation has a reference to the Module object and will keep it alive until the compilation is finished.

V8 does it very similarly, except that compilation does not keep the module alive. We cancel compilation when the ref count drops to zero.
But note that the WasmModule is only created when baseline compilation finishes, so up until this point compilation cannot be cancelled because there is a promise to be resolved. So cancellation really only applies to tiering.

@lukewagner
Copy link
Member

If you use the wasm streaming JS APIs, I think this already Just Works. E.g., if you have:

var controller = new AbortController();
WebAssembly.compileStreaming(fetch(url, {signal: controller.signal})).then(...);

then if you controller.abort(), this will cause wasm compilation to fail immediately with an AbortError.

For the ArrayBuffer compilation APIs, if the ArrayBuffer is large enough that cancellation is useful, the streaming APIs should really be used instead, for performance reasons. But technically, you could create your own stream (feeding it from the ArrayBuffer), create a Response from the stream, and then fetch() that Response, supplying an AbortSignal... but that's a bit roundabout :)

@chicoxyzzy
Copy link
Member Author

@lukewagner this won't work for Node.js and other non-browser environments.

@lukewagner
Copy link
Member

You're right, the streaming APIs are in the Web API, but I'm not sure if the solution is to have wasm's JS API to invent its own duplicate version of AbortController; ideally fetch()/Response/AbortController could be implemented in these non-browser environments, thereby enabling cross-environment portable, efficient streaming wasm compilation. I don't know how politically loaded of a solution that is, though.

@chicoxyzzy
Copy link
Member Author

chicoxyzzy commented Apr 19, 2019

Cancellation won't be possible at all until we'll have an API for that in compile and instantiate methods.

(Could we add JS embedding label for the issue?)

@chicoxyzzy
Copy link
Member Author

We now have at least one precedent of using AbortController outside of DOM spec — Web NFC now also uses it.

@chicoxyzzy
Copy link
Member Author

chicoxyzzy commented Dec 17, 2019

Web Locks API also uses AbortController.

Related discussions:

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

No branches or pull requests

6 participants