编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

2023年为何浏览器、服务端竞相使用 WebAssembly?

wxchong 2025-04-29 05:54:04 开源技术 4 ℃ 0 评论

家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!

今天给大家带来的分享主题依然是 WebAssembly ,关于 WebAssembly 的更多内容可以阅读我在头条发布的专题系列,后续也会持续关注 WebAssembly 的发展与前沿动态,希望能给大家带来帮助。话不多说,直接开始!

1.WebAssembly 历史与背景

WebAssembly 是由浏览器供应商创建的,其主要目标是在浏览器上运行应用程序时达到接近本机的速度,因为 JavaScript 运行时即使非常快,也无法达到接近本机的速度。WebAssembly 标准的灵感主要来自两个来源:asm.js 和 PNaCl。

1.1 asm.js

asm.js 是由 Mozilla 提出的一个基于 JS 的语法标准,主要是为了解决 JS 引擎的执行效率问题,尤其是使用 Emscripten 从 C/C++语言编译成 JS 的程序的效率。

Emscripten:是 Mozilla 的一个实验性项目,目的是把 C/C++开发的应用编译成 JS 或 HTML5 的应用,编译过程中需要首先把 C/C++程序编译成 LLVM 的中间代码,然后再转换成 JS 代码,这样做可以很好地复用现有的针对 LLVM 的优化。

asm.js 是 JS 的一个子集,旨在将“typing(类型)”包含到 JavaScript 代码中,因此浏览器中的 JS 运行时可以轻松地将它们优化为最佳机器代码。

目前来说,asm.js 主要由 Emscripten 使用。如上所言,Emscripten 是一种源到源转换器,可将 LLVM 位码转换为 JS 代码。由于几乎所有 C/C++ 程序都可以很容易地转换为 LLVM 位码,这有助于使大量 C/C++ 程序在浏览器中可用,从而助力 WebAssembly 推广。

1.2 PNaCl

Google 开发了 NaCl(Native Client)和 PNaCl(Portable Native Client)。

PNaCl 是在 Google 的 Native Client(NaCl)基础上创建的,可以将本地代码的性能和初级控制带到现代 Web 浏览器里,同时兼具安全性和 Web App 的可移植性。除此之外,NaCl 还能够让开发者充分利用 CPU ,如:GPU 的性能、特点,从图片编辑、音频混合到 3D 游戏、CAD 建模等方面来构建 Web App。

PNaCl 是一项伟大的技术进步,但它只得到了一家厂商的支持,即谷歌。WebAssembly 吸取了 PNaCl 和 asm.js 的成功经验,并成为现在被所有行业(Google、Mozilla 和 Apple)采用的新标准

2.浏览器中的 WebAssembly

WebAssembly 是一种开放标准,它定义了可执行程序的可移植二进制代码格式、相应的文本汇编语言,以及用于促进此类程序与其宿主环境之间交互的接口。

WebAssembly 让开发者可以在浏览器中运行更广泛的编程语言(例如 Rust、C、C++ 等),并以一种通用、可移植和安全的方式在浏览器之外运行。WebAssembly 具有以下明显特性:

  • 便携
  • 快速
  • 沙盒

2.1 主流浏览器支持

现在所有主流浏览器(Google Chrome、Safari、Edge、Firefox 和 Opera)都支持 WebAssembly,截至 2019 年 11 月,WebAssembly 已然成为 W3C 推荐标准。通过在浏览器上使用 WebAssembly,可以做到:

  • 提高 Javascript 应用程序的速度,消除 CPU 密集型计算的瓶颈
  • 在网络应用程序中使用更多编程语言(JS 除外)

2.2 WebAssembly 确实比 JavaScript 快

多年来,浏览器一直在竞相提高浏览器中 JavaScript 程序的执行速度,并衍生出了最先进的 JS 运行时,例如:

  • V8(谷歌浏览器):Node、Deno 等底层 JavaScript, TypeScript, WebAssembly 运行时使用
  • JavascriptCore(Safari):Bun 史上最快运行时扩展了 JavaScriptCore,即为 Safari 构建的 JS 、WebAssembly 引擎。
  • SpiderMonkey(Firefox): Mozilla Firefox 中使用的 JavaScript 引擎,支持 JavaScript、WebAssembly 运行工作。

然而,当运行一个简单的 JS 程序时,Javascript VM 需要做很多检查以符合 JS 规范。与此相比,Wasm 程序则是提前编译和优化的。

从这个意义上说,WebAssembly 规范比 JS 规范偏底层得多, 同时更容易将 WebAssembly 字节码翻译成机器可以运行的机器码,从而产生更快的速度提升。以下是使用 WebAssembly 带来性能提升的实际示例:

  • Tensorflow:借助 WebAssembly 实现了 2 倍的速度提升
  • Figma:切换到 WebAssembly 后,无论文档大小,应用加载时间都缩短了 3 倍以上
  • PhotoShop:借助于WebAssembly将PS移植到浏览器

更多WebAssembly的成功示例可以参考、阅读我的另一篇博文《2023年让 WebAssembly 大火的10+前端工具和应用!》,这里不再做过多的展开。

2.3 浏览器支持更多编程语言

由于 WebAssembly 越来越受欢迎,越来越多的编程语言一直在尝试编译到 WebAssembly ,以此来增加它们的使用。Rust 更是将 WebAssembly 视为其生态中的一等公民,这也快速普及了 Rust 程序在浏览器中的覆盖。

除了 Rust 外,还有更多的编程语言也可以在浏览器中运行:

  • C/C++:通过 Emscripten 或 Wasienv 等编译
  • Go:原生支持
  • Java:通过是要用 CheerpJ、GWT、 TeaVM 、Jsweet、J2CL、JWebAssembly 等类似转译器。这些转换器我已经单独行文介绍,可以在主页阅读。
  • .Net / C#:通过 Blazor

3.服务器中的 WebAssembly

尽管 WebAssembly 最初设计为在浏览器中运行,但它在服务器端也正在获得广泛的采用。主要归功于 WebAssembly 的设计原则和独特性:

  • 快速&轻便
  • 可移植的:它可以在任何平台和架构中运行
  • 沙盒

这些属性使 WebAssembly 成为运行不受信任代码方式的理想竞争者,可以在任何地方安全、快速地运行,特别是在浏览器之外。

以下是使用 WebAssembly 服务器端的一些用例。

3.1 通用程序(Universal programs)

以前,程序只能在特定的平台和架构中运行。 例如,Windows 的程序无法在 Mac(不同平台)上运行,或者 Mobile 程序无法在 Desktop(不同架构)上运行。

主要原因是技术性的,即程序二进制文件只能在平台和架构上执行。

然而,还有其他解决方案,如 JVM 或基于操作系统的容器(如 Docker),开启了普遍运行单个字节码文件的可能性。但是,这两种方法在通用程序方面都不如 WebAssembly。 原因如下:

  • JVM 是一个非常可靠但很重的 VM, 仅 JVM VM 和框架就大约 200Mb。 除此之外,JVM 不能在浏览器中轻松运行,它的发展主要由一个私有组织(Oracle)领导,而不是像 Wasm 那样由一个标准委员会领导。
  • Docker 是一个基于操作系统的容器, 即它在容器中有一个完整的操作系统,以便能够运行程序。 与 WebAssembly 程序相比,这使得 Docker 容器在初始化时既慢又大。 同时,Docker 容器与平台无关,但依赖于芯片组。

3.2 边缘计算与物联网 IOT

云计算是允许应用程序和公司轻松扩展而无需担心物理服务器的第一个趋势。 然而,一旦大多数公司接受了这一趋势,计算能力就会更加集中到更少的人手中(比如:亚马逊网络服务、微软 Azure 和谷歌云等等)。

随着 5G 的新趋势,现在可以在以前不可能的地方(路由器、物联网设备等)运行软件,从而形成一个更加去中心化的生态系统。正因为如此,WebAssembly 是边缘计算的强大竞争者,因为它允许以轻量、通用和安全的方式在这些地方运行软件。

3.3 通用库/插件

想在其他语言(例如: JS 或 Python 生态系统)中使用 C/C++ 库是极具挑战的,因为开发者必须编写插件语言(如: C/C++ 或 Rust)与宿主语言(JS 或 Python)之间的所有绑定。

然而,WebAssembly 是适用于任何语言库的理想格式。

3.4 区块链和去中心化平台

比特币是第一个在存储层面(区块链)推广去中心化信任的平台。

在区块链成为主流之后,像以太坊这样的新平台引入了一种方法,不仅可以对存储(区块链)进行去中心化信任,还可以对执行(智能合约,作为每次交易发生时运行逻辑的一种方式)进行去中心化。

以太坊创建了自己的 VM (EVM) 来运行此智能合约,以及受流行语言(分别为 JavaScript、Python)启发的新语言(Solidity、Vyper),以便开发人员可以轻松使用此合约。

然而,随着时间的推移,智能合约开发人员意识到 EVM 方法存在一些问题:

  • 不能重用已经存在于其他语言中的程序
  • EVM 机器并不像希望的那样最佳/快速

正因为如此,去中心化平台推动从 EVM 模型转移到基于 WebAssembly 的新架构,即 ewasm,这样做有以下明显的好处:

  • 可以用编译成 WebAssembly 的语言创建智能合约,从而重用现有编程语言的代码
  • 智能合约将在任何地方以最佳、安全和普遍的方式运行

4. WebAssembly 的表现形式

WebAssembly 代码(表示程序的代码)可以用两种方式表示,比如:二进制、文本。

4.1 WebAssembly 二进制格式

WebAssembly 的二进制格式设计为:

  • 体积小: WebAssembly 程序很小
  • 易于扩展:随着 WebAssembly 的发展,它最大限度地减少了重大变化
  • 快速解析:运行时读取字节码的工作量最小

下面是一个 WebAssembly 二进制文件的示例:

// add.wasm (二进制格式)
0061 736d                                 ; WASM_BINARY_MAGIC
0100 0000                                 ; WASM_BINARY_VERSION
01                                        ; section code
00                                        ; section size
01                                        ; num types
60                                        ; func
02                                        ; num params
7f                                        ; i32
7f                                        ; i32
01                                        ; num results
7f                                        ; i32
07                                        ; FIXUP section size
03                                        ; section code
00                                        ; section size (guess)
01                                        ; num functions
00                                        ; function 0 signature index
02                                        ; FIXUP section size
07                                        ; section code
00                                        ; section size (guess)
01                                        ; num exports
03                                        ; string length
6164 64                                   ; export name "add"
00                                        ; export kind
00                                        ; export func index
07                                        ; FIXUP section size
0a                                        ; section code
00                                        ; section size
01                                        ; num functions
00                                        ; func body size
00                                        ; local decl count
20                                        ; local.get
00                                        ; local index
20                                        ; local.get
01                                        ; local index
6a                                        ; i32.add
0b                                        ; end
07                                        ; FIXUP func body size
09                                        ; FIXUP section size

如上所示,二进制文件不容易被人类读取。

4.2 WebAssembly 文本格式

WebAssembly 核心团队还创建了一种可转换为二进制格式的文本格式。下面代码是前面 WebAssembly 程序的一段文本表示形式:

// add.wat(WebAssembly的文本表示)
(module
  (func $add (param $lhs i32) (param $rhs i32) (result i32)
    local.get $lhs
    local.get $rhs
    i32.add)
  (export "add" (func $add))
)

5.本文总结

本文主要和大家探讨WebAssembly的起源、WebAssembly的特性、为什么浏览器、服务端都竞相使用 WebAssembly。当然,因为篇幅有限,文章并没有过多展开,如果有兴趣,可以在我的主页继续阅读,同时文末的参考资料提供了大量优秀文档以供学习。最后,欢迎大家点赞、评论、转发、收藏!

参考资料

英文链接:
https://www.webassembly.guide/webassembly-guide/webassembly/webassembly-in-the-server

翻译作者:头条高级前端进阶,有大量改动、自组织

https://www.linuxlinks.com/spidermonkey-javascript-webassembly-engine/

https://spidermonkey.dev/blog/2023/02/16/newsletter-firefox-110-111.html

https://spidermonkey.dev/blog/2023/02/16/newsletter-firefox-110-111.html

封面图来源地址:
https://www.dpss.inesc-id.pt/~nsantos/msc-topics/msc-topics-WS.html

https://linux.cn/article-11823-1.html

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表