-
Notifications
You must be signed in to change notification settings - Fork 37
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
Comparison with wasm2c
+ some ideas
#1
Comments
Features comparison.
These are implemented in Other important proposals include:
These (AFAIK at the time of writing) are not available in P.S. I think I can add |
Coremark 1.0 results
|
Thank you for this analysis Volodymyr! These are great points for the README, I will detail better which features are supported and also which are not, and the trade-offs / goals of the project itself. PerformanceI had no idea clang was itself available as a WebAssembly binary, amazing! This is a great stress-test. My main goal is porting new software to older machines, which have only tens of MHz and memory, ideally on the host itself (no cross-compiling). This is why I looked into streaming compilation (no IR), but also took a few short-cuts. For now I have focused on getting the test suite to pass and some small programs to compile and run. So far I have not focused on any performance optimizations, other than employing a streaming-compilation approach. It is great to see that even large programs like clang can be translated and performance is already good. I think there are multiple opportunities to improve the performance and resource footprint further, by improving memory allocation, improving speed by parallelizing compilation, and especially for reducing size by removing the unnecessarily generated code:
Great point about compiling large C files: This is one of the reasons I started this project. SwiftWasm generates very large WebAssembly binaries, which take long to compile to C and then very long to compile to a native binary. I am currently working on parallel compilation, where the compiler is writing function implementations into several smaller files that can be compiled independently, and also performing this code generation concurrently. This will hopefully make compiling the resulting C code more manageable and also speed up the translation process from WebAssembly to C. FeaturesFor now I have focused on supporting the core specification 1.0 as outlined in https://www.w3.org/TR/wasm-core-1/. I have not looked into new approved features, like the ones you listed, mostly because I was not sure if they are needed for compiling applications and libraries written in C, C++, Rust, Swift, etc. It seems that most compilers seem to target the "MVP" specification. As for the concrete proposals you listed:
Do you know if there are certain compilers targeting WebAssembly that leverage or even require these feature? Coremark resultsPerformance should be very similar to wasm2c, as the generated code pretty much the same. wasm2native integrationThis looks like a great project! I was looking for a wasi implementation for wasm2c, awesome work! Currently the API that w2c2 provides is slightly different than wasm2c, and it produces differently mangled names (mostly they are shorter, e.g. don't include type information). I think this difference could be worked around or even removed. |
Some thoughts (great project btw!):
Several of those features are implemented in LLVM and are optional in the Emscripten and Rust toolchains for example. But they are not required, so projects using them could just be recompiled for wasm 1.0. Exceptions is maybe the hardest of those. You can compile C++ exceptions and longjmp with wasm 1.0 today, but then you have to use the Emscripten EH model which requires supporting some extra imports (emscripten's wasm2c layer emits them), but also it is probably slower than wasm EH. Overall, my guess is that compiling wasm 1.0 to C is "good enough" for most things in the C/C++/Rust/Zig/etc. world today. Exceptions maybe raise the question of compiling to C++ instead, and wasm GC maybe suggests compiling to a GC language, but maybe those features would be out of scope of this project anyhow?
I would guess nothing is needed in w2c2 or wasm2c for performance since the C compiler does the hard work anyhow. The big question is whether there are things that wasm->C translation can optimize that a C compiler can't, but it's hard for me to think of anything... |
@kripken Thank you for answering my questions, that makes a lot of sense!
I have no immediate plans for generating other code in other languages, but even though the C code generation (in
I mostly focused on streaming code generation and assumed that tools like binaryen's wasm-opt can take care of optimizations and w2c2 does not need to reinvent the wheel here. It is likely that such pre-C optimizations are actually useful, as older C compilers likely do not have as advanced optimizations as modern compilers, though I have not tested this yet. |
@vshymanskyy I've added support for parallel compilation in #2. Going to work on reducing the output size now |
With #3 merged, the output size is now reasonable |
@vshymanskyy That's great to hear! Linking I saw you started work on a WASI implementation for wasm2c in wasm2native, great work! It would be nice to leverage this existing work and not have to re-implement the WASI spec specifically for w2c2 again. First step would be to make the API of the generated code of w2c2 match that of wasm2c. I started looking into the differences and noticed that wasm2c includes the parameter types and return types in the mangled names of the imports and exports – is this really necessary? I also wonder what the minimum requirements for uvwasi and especially libuv are (C standard, endianness, etc.) |
WASI implementation improvements are work in progress in #4 |
Both target C89 and run on little and big endian machines. |
I was able to add #define Z_fd_prestat_getZ_iii fdX5FprestatX5Fget
#define Z_fd_prestat_dir_nameZ_iiii fdX5FprestatX5FdirX5Fname
#define Z_environ_sizes_getZ_iii environX5FsizesX5Fget
#define Z_environ_getZ_iii environX5Fget
.... Along with customized @turbolent When generating multiple files with With this I was able to build multiple rather complex wasi apps.
|
Ok, got it working. |
@cjihrig that's great! Thank you for the information 👍 https://github.com/libuv/libuv/blob/v1.x/SUPPORTED_PLATFORMS.md looks good too, I'll try on some of my older machines (e.g. Mac OS X < 10.7, especially on PowerPC; IRIX on MIPS; OpenStep/NeXTSTEP on x86/PowerPC/HPPA) |
@vshymanskyy Wow, nice! It didn't even occur to me to use the pre-processor to add compatibility, great idea 👍 Also, thank you for the bug report and also the fix! Great to hear clang builds in reasonable time 🎉 Maybe it can be sped up with |
@turbolent do all/any of these platforms support CMake? Do you compile on the target, or do you cross-compile?
|
I'd like to get rid of CMake dependency for |
@vshymanskyy Node.js builds libuv with gyp. I'm not sure if you can use it for inspiration, but here is the gyp file. |
@vshymanskyy For Mac OS X 10.4/10.5 tigerbrew provides CMake 3.6, I'm not sure if that's enough. As for big-endian support: wasm2c and w2c2 both use "negative memory" (see the end of https://skmp.dev/blog/negative-addressing-bswap/), so access in memory
|
@vshymanskyy I now have enough of a WASI implementation that should be able to run Do you have instructions on how you compiled/created |
@turbolent thanks for explanations on Big-Endian, will check it soon. Just checked my clang compilation. For this test I replaced I didn't push my changes to |
Overall, it may be a good idea to move wasi implementation into a separate project. It's rather complicated, esp. if targeting multiple OS environments. |
@turbolent just pushed changes to wasm2native. You should be able to: git clone https://github.com/vshymanskyy/wasm2native.git
cd wasm2native
export CC="clang-12"
export LDFLAGS="-fuse-ld=lld"
./build.sh path/to/clang.wasm To run the resulting |
@vshymanskyy Great to see you've added support for w2c2! I've got When compiling |
Awesome! 🙌 |
Update: The WASI implementation now has support for big-endian machines and QEMU's user mode emulation is really useful for development, but also has some issues, e.g. when using it on a 64-bit host running 32-bit executables and performing filesystem operations. |
With some efforts, it should be possible to |
@turbolent , |
@vshymanskyy Wow, awesome! This is actually going to be really useful on platforms with bad C compilers (e.g. the SGI MIPSpro compiler on IRIX) 👍 |
As mentioned above, I ran into linking errors for clang on Mac OS X 10.4 on PowerPC. I assumed this was due to large static arrays that are generated for the data segments. I found some platform-specific ways of embedding the data segments directly in the binary without having to generate large array literals in the source in #8. This is generally useful, however, I am still getting linker issues for the example above, probably due to the binary being too large and jump instructions overflowing? |
Just performed a quick test to understand how it compares to
wasm2c
.For this test I took a ~25 MB wasm (WASI) file,
clang.wasm
w2c2
finishes in 5.1s, RAM usage: 193 Mb. Output: 1.3 GiB file (34.8 Mb zipped)wasm2c
finishes in 1m23s, RAM usage: 1432 Mb. Output: 301 MiB file (22 Mb zipped)Clearly, speed and RAM usage are really good 🎉 🚀
Wondering if file size can be reduced 🧑🔬
This also brings another question. C compilers are not very efficient when working with huge C files, so monsters like
clang.wasm
will take ages to compile. This is mentioned in mywasm2native
tool: https://github.com/vshymanskyy/wasm2native#todoOne of the possible solutions is to split output into smaller chunks (which also enables parallel build).
The text was updated successfully, but these errors were encountered: