WASM cache: POC
This is a POC for compiled WebAssembly module cache proposal (#36671).
Checklist
- [ ]
make -j4 test(UNIX), orvcbuild test(Windows) passes - [ ] tests and/or benchmarks are included
- [ ] documentation is changed or added
- [ ] commit message follows commit guidelines
@devsnek
I think this seems better suited to userland.
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
-
The only way to deserialise a WASM module in public V8 API is to use the infrastructure supporting
.compileStreaming. @addaleax -
WebAssembly.compileStreamingis not available, unlessWasmStreamingCallbackwas registered with V8 prior to startup. Makes it challenging to implement the feature as a standalone module.
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.
WebAssembly.compileStreaming workflow
- Embeder registers a WASM streaming callback. This has to be done prior to V8 startup, otherwise
compileStreamingwon't be available. compileStreaming(input)will pass theinput(resolving thePromiseif necessary) to the registered callback, along withWasmStreamingobject.- The callback should verify that
inputis something it could stream from, V8 itself doesn't check theinput. - The callback uses
WasmStreamingobject to feed the module in:.SetClient(client)— request a notification once the Module is compiled and optimised.SetUrl(url).SetCompiledModuleBytes(bytes)— pass the previously compiled and optimised module.OnBytesReceived(bytes)— transfer a chunk.Finish()- or
.Abort()
- Once
.Finish()was called, V8 starts Tier 1 compiler. - When Tier 1 completes, the Promise returned from
.compileStreamingresolves, and the Module becomes available. It's not optimised yet. - Tier 2 continues in the background.
- Tier 2 completes, V8 transparently replaces the Module code with the optimised version.
- A client, if registered with
WasmStreaming.SetClient, is notified. It could extract the optimised compiled module bytes and save it to cache. Only optimised version is cacheable.
Concerning WebAssembly.compileStreaming (sidenote)
Node.js doesn't expose .compileStreaming at the moment. As a side effect of the proposed changes, it gets exposed. This is probably wrong. According to the spec, is is taking a Request object. There's no such thing in Node.js.
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.
See https://github.com/nodejs/node/issues/36671#issuecomment-768257129.