Search code examples
c++compiler-optimizationwebassemblywasi

How to reduce size of WASM binary?


I have a project written in C++, and the platform to be deployed in has a limitation of 256KB of binary size.

The toolchain is wasi-sdk-16.0 clang++, we use this compiler to compile the source code into binary in WASM format. In this step we compile the sources with the following CXX_FLAGS.

-fstack-protector-strong -Os -D_FORTIFY_SOURCE=2 -fPIC -Wformat -Wformat-security -Wl,-z,relro,-z,now -Wno-psabi

Then we strip the binary with

strip -s output_binary.wasm

After steps above, the compiled binary size in this step is 254KB.

Then we use wamrc in WAMR to compile the WASM binary with AOT runtime, the command is shown below.

wamrc --enable-indirect-mode --disable-llvm-intrinsics -o output.aot output.wasm

the output binary size become 428KB, much bigger than the limitation (256KB).


After google'd, I use wasm-opt to reduce size,

wasm-opt -Oz output.wasm -o output.wasm

The size become 4KB smaller. (almost useless)


I tried to comfirm how much does my code affects the binary size, so I write simple minimum sample code just called the standard c++ library, as the following,

#include <vector>
#include <iostream>

int main() {
    std::vector<int> vec = {1,2,3,4,5};
    for (auto v: vec) {
        std::cout << v << " ";
    }
}

The binary size after compiled has alrealy become 205KB.


I also tried to use a binary size profiler (twiggy) to track the size of each part of the bianry, but the tool failed to open this binary.


So I want to ask

  1. While just including two standard C++ headers makes the binary size reach the size limitation, how can I strip the C++ standard library with the function I really use(I cannot use strip unused function flag because my project is a library provide to others), or is really the c++ standard library affected the binary size?

  2. Is there any other compiler flags, or strip flags, or any other optimization tools can significantly reduce the binary size?


Solution

  • I solve this issue with just replacing iostream and fstream to cstdio. It reduces size from 254KB to 85KB, because there contains too many templates in iostream.

    Using iostream Count of functions (with readelf -Ws) Size of Binary
    Yes 685 254KB
    No 76 85KB

    While specifying compiler flags such as -Oz also reduces some size, but the main factor is too many codes were generated from templates. So, do not use C++ stream API (and any other template-heavy general-purpose libraries) when there are binary size limitations. (C libraries are always worth to believe.)