使用 Emscripten 编译的 WebAssembly 能否生成更小的文件大小
Can WebAssembly compiled with Emscripten generate smaller file sizes
我对 WebAssembly 非常感兴趣,但令我失望的是,即使是 "Hello World" 示例,用 C++ 编码并使用 Emscripten 编译,在浏览器中加载总计 396KB。是什么赋予了?如何使它更节省空间?
The higher optimization levels introduce progressively more aggressive optimization, resulting in improved performance and code size at the cost of increased compilation time. - Source
这就是 emscripten 文档关于缩小文件大小的说法。请注意,更高级别的优化并不意味着更小的文件大小。每个优化选项的行为都不同,这在 docs.
中有很好的描述
以下示例使用 -Os
代码优化选项,使编译器的行为如下:
Like -O3, but with extra optimizations that reduce code size at the expense of performance. This can affect both bitcode generation and JavaScript. - Source
emcc -Os file.cpp
总结
- 对于像游戏引擎这样的大型项目,与小型 Hello World 示例相比,Emscripten 生成的代码的开销按比例减少。
- Emscripten 最近在缩小代码大小方面取得了很大的改进。确保使用最新的 Emscripten 版本。
- 添加
-Os –closure 1
可能会将生成的代码大小减少 10 倍。
下面是回答问题的说明how can this be made more size-efficient
为什么会生成这么多代码?
生成的 Webassembly 数量与编写的 C++ 代码量以及该代码的依赖项成正比。依赖于标准库的 C++ 程序所依赖的代码比您预期的要多。像这样的简单 add()
函数...
int add(int x, int y) {
return x + y;
}
..将生成一个简短的 Webassembly 函数,如下所示:
(func $add (param $x i32 $y i32) (return i32)
(get_local 0
get_local 1
i32.add))
但是对 printf
的调用将需要定义 strlen
、flockfile
、funlockfile
、memcpy
、[=20= 等函数]、fputs
、__stdio_write
,即调用 printf
所需的标准库中的所有函数。本机环境中的 C++ 程序 运行 将仅链接到平台的适当 libc,但 Webassembly 需要携带那些 库依赖项 沿着。
除了用户空间库依赖,生成Webassembly的工具还需要提供一个运行时环境来处理系统调用。因此,Hello World 程序需要具有覆盖分配内存和写入字节的系统调用的定义。
编译器如何缩小代码大小?
emscripten 的创建者和维护者 Alon Zakai 撰写了 Mozilla Hacks 文章 Shrinking Webassembly and Javascript code sizes in Emscripten。我要在这里总结那篇文章的要点:
Emscripten 最初专注于通过为系统调用实现 libc 和运行时来提供 Posix 环境,从而轻松移植现有的 C 和 C++ 程序。为了方便起见,通常会包含比需要更多的代码。
很多运行时是作为 Javascript 代码实现的。 Emscripten 生成的代码在 application/library Webassembly 代码和 Javascript 运行时之间来回调用。
从不调用的代码应删除。在由称为 Dead Code Elimination 的优化处理的编译器中。 Emscripten 构建所有函数的图形并删除那些从未从 main 中调用的部分。好的,这不是严格正确的,但足以解释这个问题。
但是编译器以前无法为跨越 Webassembly 和 Javascript 之间边界的调用生成那种图形。随着 wasm-dce tool 的加入,情况发生了变化。现在,Emscripten 可以创建 Webassembly 和 Javascript 代码的图表。
Hello World 程序"shrinkage"的限制是多少
printf
是对文件描述符进行操作的通用函数,即thread-safe。几乎所有为 printf 调用生成的代码都必须存在。
如果您想对生成的代码进行更多试验,我推荐 Webassembly Studio 在线 IDE。它提供了一个示例 Hello World 项目,其中包含一个自述文件,其中介绍了生成的库代码和运行时 Javascript 代码。
当 wasm 实现 DOM/web API 时,您将获得更小的尺寸和更好的性能,因此您需要回调 javascript .
我对 WebAssembly 非常感兴趣,但令我失望的是,即使是 "Hello World" 示例,用 C++ 编码并使用 Emscripten 编译,在浏览器中加载总计 396KB。是什么赋予了?如何使它更节省空间?
The higher optimization levels introduce progressively more aggressive optimization, resulting in improved performance and code size at the cost of increased compilation time. - Source
这就是 emscripten 文档关于缩小文件大小的说法。请注意,更高级别的优化并不意味着更小的文件大小。每个优化选项的行为都不同,这在 docs.
中有很好的描述以下示例使用 -Os
代码优化选项,使编译器的行为如下:
Like -O3, but with extra optimizations that reduce code size at the expense of performance. This can affect both bitcode generation and JavaScript. - Source
emcc -Os file.cpp
总结
- 对于像游戏引擎这样的大型项目,与小型 Hello World 示例相比,Emscripten 生成的代码的开销按比例减少。
- Emscripten 最近在缩小代码大小方面取得了很大的改进。确保使用最新的 Emscripten 版本。
- 添加
-Os –closure 1
可能会将生成的代码大小减少 10 倍。
下面是回答问题的说明how can this be made more size-efficient
为什么会生成这么多代码?
生成的 Webassembly 数量与编写的 C++ 代码量以及该代码的依赖项成正比。依赖于标准库的 C++ 程序所依赖的代码比您预期的要多。像这样的简单 add()
函数...
int add(int x, int y) {
return x + y;
}
..将生成一个简短的 Webassembly 函数,如下所示:
(func $add (param $x i32 $y i32) (return i32)
(get_local 0
get_local 1
i32.add))
但是对 printf
的调用将需要定义 strlen
、flockfile
、funlockfile
、memcpy
、[=20= 等函数]、fputs
、__stdio_write
,即调用 printf
所需的标准库中的所有函数。本机环境中的 C++ 程序 运行 将仅链接到平台的适当 libc,但 Webassembly 需要携带那些 库依赖项 沿着。
除了用户空间库依赖,生成Webassembly的工具还需要提供一个运行时环境来处理系统调用。因此,Hello World 程序需要具有覆盖分配内存和写入字节的系统调用的定义。
编译器如何缩小代码大小?
emscripten 的创建者和维护者 Alon Zakai 撰写了 Mozilla Hacks 文章 Shrinking Webassembly and Javascript code sizes in Emscripten。我要在这里总结那篇文章的要点:
Emscripten 最初专注于通过为系统调用实现 libc 和运行时来提供 Posix 环境,从而轻松移植现有的 C 和 C++ 程序。为了方便起见,通常会包含比需要更多的代码。
很多运行时是作为 Javascript 代码实现的。 Emscripten 生成的代码在 application/library Webassembly 代码和 Javascript 运行时之间来回调用。
从不调用的代码应删除。在由称为 Dead Code Elimination 的优化处理的编译器中。 Emscripten 构建所有函数的图形并删除那些从未从 main 中调用的部分。好的,这不是严格正确的,但足以解释这个问题。
但是编译器以前无法为跨越 Webassembly 和 Javascript 之间边界的调用生成那种图形。随着 wasm-dce tool 的加入,情况发生了变化。现在,Emscripten 可以创建 Webassembly 和 Javascript 代码的图表。
Hello World 程序"shrinkage"的限制是多少
printf
是对文件描述符进行操作的通用函数,即thread-safe。几乎所有为 printf 调用生成的代码都必须存在。
如果您想对生成的代码进行更多试验,我推荐 Webassembly Studio 在线 IDE。它提供了一个示例 Hello World 项目,其中包含一个自述文件,其中介绍了生成的库代码和运行时 Javascript 代码。
当 wasm 实现 DOM/web API 时,您将获得更小的尺寸和更好的性能,因此您需要回调 javascript .