Repository navigation
WASM cache: POC - #36672
WASM cache: POC#36672mejedi wants to merge 7 commits into
Conversation
devsnek
left a comment
There was a problem hiding this comment.
I think this seems better suited to userland. Additionally, compileStreaming has long been a source of contention and if you wanted to use that (which there is no point in doing in this case at least, since you aren't streaming anything, so WebAssembly.compile would be fine), you should probably split that into its own PR.
There are some technical difficulties. Please check the overview below. Personally, I don't see how this could be made into a standalone package (I guess this is what you are suggesting), could you please elaborate? Short version
Compiled WASM module cache is paramount for a good WASM experience, I wonder why you are convinced this should be standalone. It's hard to claim that WASM is out of scope for Node.js, since WASI is already in core.
|
|
I would imagine V8 could be modified to support caching in WebAssembly.compile. In that case, the callback wouldn't need to be registered before the context is created, and you could do it from userland. |
| break; | ||
| } | ||
|
|
||
| let cacheDir = path.resolve(os.homedir(), cacheSubdir); |
There was a problem hiding this comment.
I see where @devsnek’s concerns are coming from – this is mixing some pretty specific I/O details with low-level functionality.
Ideally, we’d expose an API that doesn’t do any I/O, and lets the user fill that part in by specifying their own callback(s?) for that – how would that sound to you?
There was a problem hiding this comment.
@addaleax Thank you for taking look! I have a meta question: what is the best channel to discuss the feature scope / public facing APIs?
There was a problem hiding this comment.
I’m not sure, but probably this PR itself – although I can see that this might turn into a long discussion…
There was a problem hiding this comment.
Ideally, we’d expose an API that doesn’t do any I/O, and lets the user fill that part in by specifying their own callback(s?)
We could do it differently:
- either provide a low-level WebAssembly
deserialiseprimitive, let the user build on top, - or build a higher-level api with the caching largely taken care of,
- something in-between?
Personally, I believe 2 is more valuable. Pros:
- implementing caching properly is non-trivial (have to detect if the source file was changed and handle race conditions while updating the cache to name a few challenges);
- cache files end up in predictable locations, it's easy to reclaim disk space and troubleshoot issues;
- doesn't expose implementation details that are likely to change.
Furthermore, sometimes the user can't be expected to write custom caching code — consider require-ing a WASI module or Emscripten-generated wrapper.
There was a problem hiding this comment.
I think your first two Pros are really Pros for option 1? Implementing caching properly is non-trivial – hence, it’s best if a userland package addresses this, instead of adding the complexity to Node.js core and tying updates to our release schedule. And while cache files may end up in predictable locations, what those locations are may depend strongly on different user’s needs – also a good point for moving this into userland modules.
There was a problem hiding this comment.
it’s best if a userland package addresses this, instead of adding the complexity to Node.js core and tying updates to our release schedule
These are valid points. However It looks like the core itself could benefit from the cache due to this feature
https://nodejs.org/api/all.html#esm_wasm_modules
FYI, concerning the cache there’s some prior art in Python we could borrow from.
https://www.python.org/dev/peps/pep-3147/
https://docs.python.org/3/whatsnew/3.8.html#parallel-filesystem-cache-for-compiled-bytecode-files
Personally, I’m mostly interested in Emscripten use case. Having a minimal low-level api in core will work for me. So if you feel strongly about it let’s do it this way.
There was a problem hiding this comment.
What if we expose WasmStreaming to userland without inventing new interfaces?
class Foo { ... }
require('v8').registerWebAssemblyStreamer(Foo, (foo, wasmStreaming) => {
wasmStreaming.setCompiledModuleBytes(...);
wasmStreaming.setUrl(...);
wasmStreaming.onBytesReceived(...);
wasmStreaming.finish();
});
WebAssembly.compileStreaming(new Foo(...));Co-authored-by: Anna Henningsen <github@addaleax.net>
* SHOULD_SET_WASM_STREAMING_CALLBACK flag introduced, normally unset. * .wasm_streaming_callback field accessed iff the flag is set, hence backwards-compatible. * Node's WasmStreamingCallback exposed so that embedder could have a custom callback without disabling Node's features built around the streaming callback.
|
See #36671 (comment). |
This is a POC for compiled WebAssembly module cache proposal (#36671).
Checklist
make -j4 test(UNIX), orvcbuild test(Windows) passes