c++ 如何减少WASM二进制文件的大小?

67up9zun  于 2023-01-03  发布在  其他
关注(0)|答案(2)|浏览(294)

我有一个用C编写的项目,要部署的平台有256 KB二进制大小的限制。
工具链是wasi-sdk-16.0 clang
,我们使用此编译器将源代码编译为WASM格式的二进制代码。在此步骤中,我们使用以下CXX_FLAGS编译源代码。

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

然后我们用strip二进制

strip -s output_binary.wasm

经过以上步骤,本步骤编译后的二进制文件大小为254 KB。
然后我们在WAMR中使用wamrc,使用AOT运行时编译WASM二进制文件,命令如下所示。

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

输出二进制大小变为428 KB,远大于限制(256 KB)。
谷歌搜索后,我使用wasm-opt来缩小尺寸,

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

大小变小4KB.(几乎无用)
我试着确认我的代码对二进制大小的影响有多大,所以我写了简单的最小样本代码,就叫标准c++库,如下所示,

#include <vector>
#include <iostream>

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

编译后的二进制大小已变为205 KB。
我还尝试使用二进制大小分析器(twiggy)来跟踪bianry每个部分的大小,但是该工具无法打开此二进制文件。
所以我想问
1.虽然只包含两个标准C头文件会使二进制大小达到大小限制,但我如何才能用我真正使用的函数剥离C标准库(我不能使用剥离未使用的函数标志,因为我的项目是一个提供给其他人的库),或者C++标准库真的会受到二进制大小的影响?
1.是否有其他编译器标志、strip标志或其他优化工具可以显著减少二进制文件的大小?

50few1ms

50few1ms1#

有一件事我没有看到你的文章中提到的是wabtwasm-strip。我对它不够熟悉,不知道它是否比简单的strip命令更有用,但也许它值得一试。你可以在Debian系统上安装apt install wasm-strip
从我在互联网上看到的一些微基准测试来看,C++ wasm二进制代码有很大的开销。对于一个完全不科学的幻灯片,你可以看this
如果由于某种原因,您无法使用该语言生成更小的二进制文件,您可以尝试在链接级别进行优化,就像busybox所做的那样。

jdgnovmf

jdgnovmf2#

    • 我通过将iostream和fstream替换为cstdio来解决此问题。它将大小从254KB减少到85KB,因为iostream中包含太多模板。**

| 使用iostream|函数计数(使用readelf -Ws)|二进制文件的大小|
| - ------| - ------| - ------|
| 是的|六百八十五|254千字节|
| 没有|七十六|85千字节|
虽然指定编译器标志(如-Oz)也会减少一些大小,但主要因素是从模板生成了太多代码。因此,当存在二进制大小限制时,不要使用C++流API(以及任何其他模板密集的通用库)。(C库总是值得相信的。)

相关问题