V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
GrapeCityChina
V2EX  ›  推广

WebAssembly 能否重新定义前端开发模式?

  •  
  •   GrapeCityChina · 2020-11-09 14:10:49 +08:00 · 1649 次点击
    这是一个创建于 1475 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如果提及近年来让人最为兴奋的新技术,非 WebAssembly 莫属。作为一种低级的类汇编语言,WebAssembly以紧凑二进制的格式存储,为 C/C++, Rust 等拥有低级内存的模型语言提供了新的编译目标。正因如此,WebAssembly 体积更小,可以以接近原生性能的速度运行。

    WebAssembly 技术本身具有非常多的优点,虽始于浏览器但已经开始不断地被各个语言及平台所集成,在实际的工业化落地中,区块链、边缘计算、游戏及图像视频等多个领域都依靠 WebAssembly 创造出了让人称赞的产品。

    WebAssembly 的应用场景

    · 编译器(编译链)

    · 多媒体剪辑

    · 游戏

    · 图像识别

    · VR+虚拟现实

    · 直播视屏特效

    · 游戏、应用分发服务

    · 服务器端运行不受信任的代码

    · 移动端混合应用

    · P2P 应用

    · …

    WebAssembly 的主要特性

    · 快速、高效、可移植

    · 可读、可调试

    · 安全,遵循浏览器同源策略和授权策略,运行在沙箱环境中

    · 与其他 web 技术兼容(JS)

    WebAssembly VS Javascript

    既然提到了 Web 技术,就不得不提另一款在 Web 项目开发中大放异彩的脚本语言 Javascript 。1995 年,Brendan Eich 用了不到 10 天就创建了 Javascript,其最初主要应用于表单验证,而非以速度见长。随着各类应用功能的复杂化,受限于 JavaScript 语言本身动态类型和解释执行的设计,其性能问题逐渐凸现。

    2008 年,围绕着浏览器性能开展的大战终于在各大浏览器厂商间爆发,在先后经历了即时编译器( JITs ),以及用 Node.js 和 Electron 构建应用程序的时期后,WebAssembly 有望成为 JS 引擎突破下一性能瓶颈的转折点。

    为此,这两者经常被用于比较,甚至一度出现 WebAssembly 终将替代 Javascript 的言论。的确,作为类汇编语言,WebAssembly 解决了 Javascript 最常为人诟病的性能问题,也正是基于此,WebAssembly 注定不适合开发人员手写代码,只能为其他语言提供一个编译目标。

    因此,这两种技术的关系不是竞争,反而更像是合作共赢。通过 Javascript API,你可以将 WebAssembly 模块加载到你的页面中。也就是说,你可以通过 WebAssembly 来充分利用编译代码的性能,同时保持 Javascript 的灵活性。

    image.png

    二者性能对比

    下图为我们展现了 JS 引擎运行程序和运行 Wasm 的耗时对比:

    image.png

    JS 引擎运行程序时,需要经历源码转换( parse )、生成字节码( compile + optimize )、编译器优化( re-optimize )、代码执行( execute )和内存清理( GC )这五个阶段:

    · parse : 将源码转换成抽象语法树,传递给解释器。

    · compile + optimize : 解释器生成字节码,并通过编译器( JIT )编译优化部分字节码,生成机器码。

    · re-optimize : 当发现优化代码无法被编译器优化时,重现转给解释器。

    · execute : 执行代码的过程。

    · GC: 清理内存的时间。

    大部分情况下,JS 在执行阶段将字节码编译成机器码,这一阶段十分耗时。(这是由于 JS 的动态性所导致,相同的代码会被不同的类型重新编译)。而 Wasm 不需要被解析,也不需要在运行时动态检测数据类型,由于它已经是字节码了,所以只需要简单解码,即可包含所有的类型信息。

    正是因为 Wasm 的大部分优化工作已经在 LLVM 的前端部分完成了,所以编译优化的工作很少,这便是其高性能的主要体现。

    编译模型(LLVM)

    image.png

    LLVM ( Low-Level-Virtural-Machine ), 底层虚拟机架构,优点包括:

    1. 模块化设计(三段式:前端、优化器、后端),代码更为清晰和便于排查问题,前端负责语法解析,生成字节码;优化器负责优字节码;后端负责生成相应平台的机器码

    2. 语言无关的中间代码,可以无限扩展而又不伤害可调试性

    3. 作为工具和函数库,易于实现新的基于编程语言的优化编译器或 VM

    WebAssembly 与 LLVM 结合

    image.png

    WebAssembly 与 LLVM 结合,不需要为各个语言额外添加前端编译工具,中间的 IL 可以不断地优化,仅需添加一个“后端”,就可以让大部分语言编译成 wasm 。这个“后端”不同于之前提到的后端,它不会直接生成机器码,它生成的 wasm,会由浏览器 wasm 运行时负责编译运行。

    这就是 WebAssembly 的编译原理, 既然 WebAssembly 的核心目标是与 Javascript 等 Web 技术兼容, 那么其兼容到底程度如何?下面,我们将通过项目实战来验证。

    项目实战:WebAssembly + Javascript

    在进入项目实战之前,大家需要理解一个核心概念,即 JavaScript 为何能完全控制 WebAssembly 代码,并执行下载和编译运行:

    核心概念

    · Module (模块):该模块表示一个已经被浏览器编译为可执行机器码的 wasm 二进制序列。模块是无状态的,它可以被缓存在 IndexedDB 中或者在 workers 之间共享,也能够像 JS 一样导入导出。

    · Memory (内存):连续大小可变的字节数组,能够被 Wasm 和 JS 同步读写。它可以用来在 JS 和 Wasm 之间传递数据,进行通信。

    · Table (表格):带类型的大小可变的数组,表格里存储了不能作为原始字节存储在内存里的对象的引用。

    · Instance (实例):一个模块及其在运行时的所有状态,包括内存,表格,以及导入的值。

    可见,JavaScript API 为开发者提供了创建模块、内存、表格和实例的能力。

    通过一个 WebAssembly 实例,JavaScript 能够调用该实例暴露的函数,把 JavaScript 函数导入到 WebAssembly 实例中,WebAssembly 也能调用 JavaScript 函数。

    另外,WebAssembly 不能直接读写 DOM,只能调用 JavaScript,并且只能传入整形和浮点型的原始数据作为参数。因此,JavaScript 能够完全控制 WebAssembly 代码实现下载、编译、运行,JavaScript 开发者也可以把 WebAssembly 想象成一个生成高性能函数的 JavaScript 特性。

    代码示例

    wasm(Rust):

    image.png

    wasm_bindgen 主要用来生成一些胶水代码,简化开发者在 JS 和 wasm 之间的方法调用。

    JS:

    image.png

    项目结构

    image.png

    IDE

    VSCode+插件 Rust

    执行步骤

    1. Install Rust:https://www.rust-lang.org/tools/install 打开 cmd,输入 cargo 确认安装是否正确。

    2. 安装 wasm 编译工具:$ cargo install wasm-pack

    3. 创建 rust-wasm 工程: $ cargo new –-lib wasmlib

    4. Build: $ wasm-pack build

    GrapeCityChina
        1
    GrapeCityChina  
    OP
       2020-11-09 14:11:07 +08:00
    具体的代码和 Demo 示例将在 11 月 11 日下午 2 点的公开课中进行演示,欢迎各位同学报名收看,报名地址: http://live.vhall.com/756593738
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   948 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 22:57 · PVG 06:57 · LAX 14:57 · JFK 17:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.