bytecodealliance / ComponentizeJS

JS -> WebAssembly Component
Apache License 2.0
205 stars 27 forks source link

Question - Should componentize-js tree shake unused imports? #104

Closed karthik2804 closed 1 week ago

karthik2804 commented 2 months ago

Should the componentizing process perform tree shaking to exclude the wasm imports not imported by the JS guest code?

An example use case is when a npm package is written for an SDK, the wit files included with it will have all the possible imports. The guest code might choose not to use all the available imports, it would be good to only generate the bindings for the imports that are actually used. It will help reduce the binary size and also could help with running the component on hosts that might not support all the imports defined in the SDK.

guybedford commented 2 months ago

This sounds like a great idea!

karthik2804 commented 1 month ago

As a follow-up to the comment, imagine the target world specifies all imports an SDK package might want to use. When a user decides to use a particular subset of the target world imports, we could potentially match the imports in the guest code using the following code to the ones in the target world. Anything in the target world not used by the guest could be stubbed out as unreachable. This would limit the number of imports that a host would have to satisfy to run the component.

I am imagining another function in addition to splice_bindings and stub_wasi that we could optionally call to stub imports in the target world that are not used.

Let me know if this makes sense. I could try to create a PoC after #109.

guybedford commented 1 month ago

Ah nice, yeah that sounds ideal I agree!

karthik2804 commented 1 month ago

The first thing I ran into was, It is not straightforward to track the implicit imports that get brought in. For example importing wasi:cli/stdin@0.2.0 in the JS guest code would also mean we need to import wasi:io. This is something I have to think about a bit more.

guybedford commented 1 month ago

I think we only need to do this for the direct imports in the splicer itself, where we synthesize all the core imports, where we would want to skip unused imports. This can be done by providing the filtered list of imports to https://github.com/bytecodealliance/ComponentizeJS/blob/main/crates/spidermonkey-embedding-splicer/src/splice.rs#L38, perhaps with a new argument "used_imports" to the main splice bindings function.

The component model already has the "gc" code to prune unused transitive imports, so the rest should follow simply from there.

karthik2804 commented 1 week ago

completed with #117