我对WebAssembly非常感兴趣,但即使是一个用C ++编写的“Hello World”示例也感到沮丧。使用Emscripten编译,在浏览器中加载总共396KB。是什么赋予了?如何才能提高尺寸效率呢?
答案 0 :(得分:7)
-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
,fwrite
等函数的定义, 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生成在应用程序/库Webassembly代码和Javascript运行时之间来回调用的代码。
应删除从未调用过的代码。在由名为Dead Code Elimination的优化处理的编译器中。 Emscripten构建所有函数的图形并删除那些从未从main调用的部分。好的,这不是严格正确的,但足以解释这个问题。
但是编译器以前不能为跨越Webassembly和Javascript之间的边界的调用生成那种图形。随着wasm-dce tool的加入,这种情况发生了变化。现在,Emscripten可以创建Webassembly和Javascript代码的图形。
printf
是一个通用函数,它对文件描述符进行操作,并且是线程安全的。为printf调用生成的代码几乎都必须存在。
如果您想更多地了解正在生成的代码,我建议使用Webassembly Studio在线IDE。它提供了一个示例Hello World项目,其中包含README,该项目可以生成库代码和运行时Javascript代码。
答案 1 :(得分:2)
更高的优化级别逐步引入更积极的优化,从而以增加编译时间为代价提高性能和代码大小。 - Source
emscripten docs关于缩小文件大小的说法。请注意,更高级别的优化并不意味着更小的文件大小。每个优化选项的行为都不同,在docs中很好地描述了。
以下示例使用-Os
代码优化选项,使编译器的行为如下:
与-O3类似,但需要额外的优化,以牺牲性能为代价来减少代码大小。这可能会影响bitcode生成和JavaScript。 - Source
emcc -Os file.cpp
答案 2 :(得分:-1)
当wasm实现DOM / web API时,您将获得更小的尺寸和更好的性能,因此您需要回调javascript。