使用Emscripten编译的WebAssembly可以生成较小的文件大小

时间:2018-02-28 17:32:02

标签: emscripten webassembly

我对WebAssembly非常感兴趣,但即使是一个用C ++编写的“Hello World”示例也感到沮丧。使用Emscripten编译,在浏览器中加载总共396KB。是什么赋予了?如何才能提高尺寸效率呢?

3 个答案:

答案 0 :(得分:7)

摘要

  • 对于像游戏引擎这样的大型项目,与小型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的调用需要包含strlenflockfilefunlockfilememcpyfwrite等函数的定义, 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代码的图形。

"收缩"的限制是什么?对于Hello World计划

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。