-
Notifications
You must be signed in to change notification settings - Fork 740
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
Add support for Wasm components in wasm-opt #6728
Comments
I think that makes sense, since I don't think there is anything If someone is interested to contribute code to Binaryen for either of those, that sounds good, though if parsing/writing components is complex then it might make sense to do it in an external tool that calls |
|
Good point, inlining would be potentially very useful here. Merging it all first makes sense, but in that case
|
At least as far as I'm aware there's no tooling for components at this time that are general purpose component-to-component optimizers. For example there's no dead-code-elimination, merging, etc.
For questions/optimizations like these it would require a much deeper understanding of a component within wasm-opt. Definitely possible to do but is a much larger step up from "just optimize each core wasm module contained in-place". Components represent a "shared nothing" boundary so you can't import/export a core wasm function/table/memory from a component. That ends up meaning that components all have a "sealed" view of the world. Modules linked together within a component are basically a way of codifying what you might do in JS glue to instantiate a module within the binary format of the component itself. Basically these sorts of optimizations are possible and there's definitely lots of possible ways to optimize a component. I suspect though that the immediate interest would basically be to just optimize the core wasm modules themselves. Performing |
I see, thanks @alexcrichton Yeah, if components have such a sealed view of the world, then merging the modules in a component first before optimizing seems a good option as @tlively said. Then things like inlining and duplicate function elimination and all that would work automatically and optimally, across what used to be module boundaries. Is there already a tool that does that merging? |
Not currently, no (or at least not that I'm aware of). It's theoretically not too hard to do but would require deeper knowledge of components and handling of the various dependencies between modules and items within a component. |
@kripken, IIUC, the point is that to do the merging in the first place, we would have to lower the component interfaces to core Wasm glue code ourselves, then merge the original componentized modules not only with each other but with that generated glue code. Is that right, @alexcrichton? |
@tlively Yeah, that definitely sounds nontrivial, but isn't that the plan for running components in the browser, to merge/lower them into an MVP module (+JS glue maybe)? I may have misunderstood though! But that is why I've sort of assumed such a tool would exist (and we wouldn't need to do work in Binaryen for it). |
Heh you're sort of both correct and I can try to provide some more background information here. I think I have given some false impressions by accident so I'll try to be more precise as well. First I'll mention that there is indeed a way to run components on the web today, and that's through jco. That works by "decompiling" a component into core wasm modules plus a wad of JS that wires everything up. This is I think what @kripken you might be referring to? I believe that Next I'll clarify that when talking about components things can be more or less complicated depending on the components you're considering. This issue, for example, was originally inspired by the output of the So to your point @tlively it sounds like you're talking about how when components all each other there's "glue" inbetween which can be expressed as wasm and Binaryen should be able to optimize this. That's definitely not something I would consider in the near term but is a possibility long-term. It's not applicable to anything coming out of LLVM at this time. Additionally the "glue" here isn't actually in the component, something would have to create it. It turns out that this is what Now what I've been talking about is something I think is completely different from what y'all are thinking. In components the idea of "shared everything dynamic linking" is that you have, for example, So with some of that let me try to also answer directly:
This is correct. This is quite a nontrivial task. Jco/Wasmtime do it and if y'all are interested I could talk more about it. The transform today never targets repackaging as a single component so care would have to be taken to ensure it's 100% semantics-perserving with what the original component wanted. Not impossible, just hasn't been a goal yet.
Yes, that's |
Is the inlining of modules inside a component really a good idea? I'm not overly familiar with the Wasm component model, but it seems to me that one goal is to allow multiple modules bundled together. If the end result of wasm-opt is to output a component that only contains a single wasm module, isn't it going against the spirit of components? And if not, is this inlining and rebundling issue not more of a compile-time issue and not for LTO? Also, I'm not sure that bundling modules together before optimizing will produce better results than optimizing each module independently (I'd like to be proven wrong on that). Additionally, having clearly separated modules is a plus for security: we can inspect the behavior of each module independently and have a layer of security between modules. I'm not saying that inlining is a bad idea, but maybe we need both options: optimization of each module inside component without structure changes and optimization with inlining if it can bring upsides. |
Thanks @alexcrichton ! Ok, then IIUC for the web the "optimize each module" approach is done or at least possible using jco. For non-web, I imagine a tool would call out to wasm-opt like jco can do now, but that tool would then repackage the optimized modules into the component once more. In theory such a tool could be in Binaryen itself, or external. For "optimize all the modules of a component together" it does seem like a lot more optimization is possible (inlining, duplicate function elimination, etc.). That could be done once there is either a smart enough wasm bundler that "flattens" all the modules in a component out into a single one, or if Binaryen parsed and understood components, so again this could be done in Binaryen or externally. As there is existing infrastructure for components outside of Binaryen then I'd guess it makes more sense to do things there. But if for efficiency or other reasons someone were interested to work on it here, that would be worth discussing of course. However, one piece of infrastructure inside Binaryen that could help here is Fair point that if someone wants the module boundaries inside a component for security or code caching or other reasons then it might not make sense to merge them all. But about this:
There could be huge optimization opportunities there. Imagine one module calls a small function in another: module A {
func foo() {
var sum = 0;
for (var i in range) {
sum += B::bar(i);
}
return sum;
}
}
module B {
func bar(i) {
return i * i;
}
} If we inline between modules, that can be module A {
func foo() {
var sum = 0;
for (var i in range) {
sum += i * i; // inlined code from bar()
}
return sum;
}
}
This situation is pretty realistic in situations like |
@kripken thanks for your example, I better see the interest for inlining now. I guess both use cases exists and are relevant then. They can be the result of different tools, or the same tool with different options depending on who is interested to develop what. TIL about A good starting point for this in |
@mh4ck-Thales An error makes sense, I agree. I opened #6751 for that now. Please take a look as I am not familiar with the component binary format. |
wasm-opt does not support running on a Wasm component, that is the default with WASIp2. wasm-opt is used for example in LLVM to optimize compiled binaries (see llvm/llvm-project#98373), which is not possible in WASIp2 for now because of this lack of support.
A possible solution may be to iterate over a Wasm component and find the core modules within it, apply current wasm-opt optimizations on each core module, then repackage the component.
Remark: I suppose all of binaryen tools can add support for Wasm components. This issue is for wasm-opt specifically but can be transformed into a more general issue.
The text was updated successfully, but these errors were encountered: