Every byte counts - Optimize them
Budgets are critical to the performance. It is very important to send down as less as possible. Check out more about the JavaScript's cost in this awesome article by Addy Osmani.
WebAssembly binaries depend on the underlying toolchain. It is important for every toolchain to optimize the binary as much as possible.
This is the reason why I fell in ❤️ with TinyGo. The WebAssembly binaries they produce are impressive and small 🦄.
In the previous post, we have seen how we can reduce 50% of the binary size by removing fmt
.
Liquid error: internal
Current binary size is 26KB
- check out this commit✨✨✨
Now we will try to reduce the binary size further.
Use the latest dev branch
Currently, we have used TinyGo version 0.6.0
. Since it is actively in development. The current dev
branch can shave off more bits. Let us use that.
Check the instructions about how to clone and build the project here. Once setup the TinyGo binary will be available inside the build
folder.
Let us build it using this TinyGo
binary.
../tinygo/build/tinygo build -o out/main.wasm -target wasm ./go/main.go
We removed 4KB
, well it is not a huge improvement. But still every byte counts
.
Current Binary size is 22KB
.
Remove custom section
The WebAssembly binary is structured as sections. There are sections for memory, imports, exports, function definition and others. Check more about it here.
The Custom Section provides the metadata information. These metadata information are used for debugging. They are not required for the normal execution of the WebAssembly. We can remove them.
Note it is completely optional while debugging this section is useful. We can remove them in production.
We can use tools like WABT. With WABT we can convert the WebAssembly Module into Text Format and then back into WebAssembly Module. This will completely remove the custom section, and strip off a few extra bytes.
We removed another 4KB
, well it is not a huge improvement again. But still every byte counts
. Now the binary is 18KB
.
Current Binary size is 18KB
.
Remove Internal panics
The Tinygo
provides a --panic
option. With this option, we can choose the panic strategy. That is, this specifies compiled program should do when a panic occurs.
We can use the --panic trap
option. This option will call the trap instruction in the platform in which it runs instead of throwing a panic.
../build/tinygo build -o out/main.wasm -target wasm -panic trap ./go/main.go
The resulting binary is 16KB. That is 2KB less.
Current Binary size is 16KB
.
Thus we reduced the code another ~40% from 26KB
to 16KB
.
Thanks to Justin Clift
The repository is here
I hope this gives you a motivation to start your awesome WebAssembly journey. If you have any questions/suggestions/feel that I missed something feel free to add a comment.
You can follow me on Twitter.
If you like this article, please leave a like or a comment. ❤️
Top comments (9)
I wonder, whether someone is trying to program in WebAssembly directly and what will be the size of the programs in this case.
Because, if we are talking about the CPU assembly language programming, it usually gives huge amount of size and speed improvement.
The program mentioned in the article is relatively simple. If imagine we want to implement it as a desktop application in Linux or Windows, my estimation is that it easily can be fit in less than 1KB and the main limitation factor will be the executable file format, not the code itself.
Loving seeing the WebAssembly content on here.
I haven't used WebAssembly much, but this article gets me really excited about just how much performance you can squeeze out of it!
Go for it... Let me know if you need help with anything :)
Any idea the sam program written in Rust would be similar in size? From the tutorial they used Binaryen and some couple of other tricks in the documentation to trim the size.
Yeah. It is possible but I doubt we can achieve this much. I haven't played with it recently. Let me check what we can achieve there.
Yeah it is awesome.
KB vs Kb
typo 🙂
So what's the main selling point of wasm? If compared to ja version,
Is the file of the compiled wasm smaller than a minified pure js script?
Is the execution speed noticeably faster?