Why is the .wasm files generated by wasmtime for just a simple print Hello World of about 2 MB
I guess it's not "generated" by wasmtime (sorry about that). But even then. I am asking here because I don't know where else to ask this question.
Are you looking at binaries built with Rust? I noticed this too, at first; it seems by default the .wasm files include debug info, and wasm-strip
(part of the WABT, WebAssembly Binary Toolkit) can remove it. I see (using a hello-world built with rustc --target=wasm32-wasi -O ...
):
$ wc -c *.wasm 1925510 helloworld-rs.wasm 71138 helloworld-rs-stripped.wasm
I used Bloaty McBloatface (https://github.com/google/bloaty/), which supports WebAssembly, to look at where the space is spent in the original (non-stripped) file:
$ bloaty helloworld-rs.wasm FILE SIZE VM SIZE -------------- -------------- 32.0% 602Ki NAN% 0 .debug_str 25.6% 481Ki NAN% 0 .debug_info 15.8% 296Ki NAN% 0 .debug_line 10.0% 188Ki NAN% 0 .debug_ranges 8.0% 149Ki NAN% 0 .debug_pubnames 3.0% 57.1Ki NAN% 0 Code 2.8% 53.6Ki NAN% 0 .debug_pubtypes 1.0% 17.9Ki NAN% 0 .debug_aranges 0.8% 16.0Ki NAN% 0 name 0.6% 11.6Ki NAN% 0 Data 0.2% 4.39Ki NAN% 0 .debug_abbrev 0.0% 251 NAN% 0 Function 0.0% 238 NAN% 0 Import 0.0% 131 NAN% 0 Element 0.0% 116 NAN% 0 producers 0.0% 108 NAN% 0 Type 0.0% 73 NAN% 0 Export 0.0% 27 NAN% 0 Global 0.0% 25 NAN% 0 .debug_macinfo 0.0% 12 NAN% 0 [2 Others] 0.0% 8 NAN% 0 [WASM Header] 100.0% 1.84Mi 100.0% 0 TOTAL
So, as seen above, most of the data is debug info that can be removed.
FWIW, I also built a hello-world in C with the WASI SDK (https://github.com/WebAssembly/wasi-sdk/), and the resulting file is 16306 bytes, so it does seem the bits of the Rust stdlib pulled in by println!
are a bit larger than the libc slice for printf
...
Yeah, it's almost certainly debug info. It'd be nice if we could move that to outside the Wasm file, but I don't think that works yet.
The Rust and WebAssembly book has a lot more information: https://rustwasm.github.io/docs/book/reference/code-size.html
Two additional things I can add here: One is that we use static linking right now, so executables include the pieces of libc they need, rather than dynamic linking them.
Another is that we've made some major improvements in the tools recently which aren't yet in a release. With a trunk build of wasi-sdk and friends, a C hello world with debug info is 29K.
Ah, and one other detail: C++ hello worlds using <iostream> are significantly bigger than C hello worlds using printf. This is because <iostream> ends up causing us to link in all kinds of locale support (that hello world itself doesn't need).
There is also twiggy
, which I wrote to better understand why some function was called and why the linker didn't gc it from the final binary: https://github.com/rustwasm/twiggy
Also, not wasm specific, but probably answers a lot of these same questions: https://lifthrasiir.github.io/rustlog/why-is-a-rust-executable-large.html
Last updated: Dec 23 2024 at 13:07 UTC