写点什么

WebAssembly 的未来:潜在新特性一览

  • 2018-08-05
  • 本文字数:4119 字

    阅读完需:约 14 分钟

WebAssembly 简介

WebAssembly 开发团队的描述:

WebAssembly(或 wasm)是一种适用于 Web 的可移植编译格式,提供更小的文件尺寸和更快的加载速度。

实际上,WebAssembly 旨在成为高级语言的编译目标。目前可以使用 C、C++、Rust、Go、Java、C#编译器(还有更多)来创建 wasm 模块。

WebAssembly 模块以二进制的格式发送到浏览器,并在专有虚拟机上执行。这个虚拟机与 JavaScript 虚拟机共享资源,如内存和线程。WebAssembly 模块总是与 JavaScript 代码一起使用,在必要的时候可以执行一些有用的操作。

目前正在进行中的很多提案旨在让 WebAssembly 成为更好的编译目标,并减少 JavaScript“胶水”代码。

WebAssembly 提案

WebAssembly 提案的流程是分阶段的,从阶段 1(不成熟)到阶段 5(完成标准化)。以下是目前所有提案的清单(前 4 个阶段),每个提案都将在后面详细介绍。

第 1 阶段(功能提案)包括以文本格式自定义注解、主机绑定、尾调用、批量内存操作、ECMA 模块集成、垃圾回收、异常处理、固定宽度 SIMD、线程。第 2 阶段(规范提议)包括 BigInt 转换。第 2 阶段(实现)包括引用类型和返回多个值。第 4 阶段(标准化)包括导出和导入可变全局变量和有符号扩展操作。

引用类型

目前的 WebAssembly 类型系统还很小,只有四种数字类型。目前,如果要使用复杂类型(例如字符串、对象、数组、结构体),需要将它们序列化为线性内存,并提供它们所在位置的引用。这个提案对类型系统进行了扩展,添加了一个新的 anyref 类型,模块可以持有对主机环境对象的引用,也就是说,你可以将 JS 对象传给 wasm 模块。

通过 anyref 引用的对象对于 wasm 模块来说意义不是很大,关键在于模块可以持有在 JS 堆上分配的对象的引用,这意味着在 wasm 执行期间需要对这些引用进行跟踪。该提案被视为垃圾回收提案的垫脚石。

返回多个值

WebAssembly 的虚拟机是基于栈的,操作对象在函数被调用之前是放在栈上的,函数会使用这些对象并替换为返回值。在目前的规范中,函数只能返回单个值。新的提案允许指令、函数和块返回多个值(例如,整数除法可以返回除数和余数)。

下面是一个简单的“swap”函数,它可以返回多个值(result i32 i32)。

复制代码
(func $swap (param i32 i32) (result i32 i32)
(get_local 1) (get_local 0)
)

导出和导入可变全局变量

目前,wasm 支持全局变量和局部变量。全局变量可以被导入和导出,并与 JS 宿主共享,不过必须将它们定义为不可变的。

新的提案将 WebAssembly.Global 构造函数添加到 JS API 中,允许导出和导入可变的全局变量。该特性对于跨多个 wasm 模块共享状态来说非常有用。

有符号扩展操作

符号扩展是一种在保留符号的同时增加二进制数位数的方法。这个提案添加了少量符号扩展指令,例如 i32.extend8_s——将有符号的 8 位整数扩展为 32 位整数。

FireFox 已经实现了这个特性,并计划在 9 月发布。

BigInt 转换

JavaScript 只有一个数字类型,即 IEEE 754 浮点数——这种表示法存在一定的局限性。现在有一个新兴的标准,即增加对“大整数”的支持,目前处于 TC39 流程的第 3 阶段。最终确定后,将为开发人员提供任意精度的整数。

WebAssembly 的四种数字类型之一是 64 位整数。新提案将提供完全的互操作,让 JS 的 BigInt 和 wasm 的 64 位整数实现双向转换。

顺便提一下,现在已经有一个用于在 JavaScript 中执行 64 位运算的库,叫作 long.js。最近,他们移除了基于 JavaScript 的实现,改用更简单的 WebAssembly!

线程

JavaScript 已经通过 WebWorker 实现了多线程,但是在 worker 之间只能使用 postMessage 进行较慢的消息传递。共享内存提案已经在 TC39 中定稿,并在 2017 年 2 月成为 ECMAScript 的一部分。共享数组缓冲区和原子性让线程之间共享数据变得更加容易。

WebAssembly 的这个提案也是允许共享访问线性内存,并提供原子操作。但值得注意的是,提案并没有引入创建线程的机制(引起了很多争议),而是由宿主提供此功能,也就是我们熟悉的 WebWorker。

我相信会有一些人对这个提案感到失望。不过,WebAssembly 之所以能够快速发展到 MVP 版本,跟团队专注于简单性不无关系。利用成熟的宿主功能(WebWorker)是非常有意义的。

将来可能会添加原生线程,但会作为单独的提案,不过这可能还需要几年的时间!

固定宽度 SIMD

单指令多数据流(SIMD)是一组支持矢量风格处理的指令,例如,将一个向量添加到另一个向量种。所有现代 CPU 都支持这些指令。有一个 SIMD.js TC39 提案,增加了很多 128 位类型,例如 float32 x 4,以及相应的操作(如 add、multiply),但最近删除了这部分内容,因为 WebAssembly 中已经添加了类似的功能。这样做是有道理的,因为这些是低级指令,而 WebAssembly 恰好是低级运行时。

WebAssembly 的 SIMD 提案非常简单,为 wasm 添加一个新的 128 位类型,可以表示四个数字的向量,以及用于创建和操作这些新类型的简单指令集。这将为某些算法类别的性能带来改进。

异常处理

程序会在出现异常时中断控制流,异常会顺着调用栈向上传播,直到遇到合适的“catch”块。异常处理是大多数现代编程语言的共同特征,尽管 Swift 在早期版本中并不支持它们。

WebAssembly MVP 在当前控制流指令中没有任何类似于异常处理的东西。因此不得不使用 Emscripten 这样的工具来模拟这个功能,但这是以牺牲性能为代价——目前,默认情况下捕获 C++ 异常是关闭的,其他语言也面临类似的问题。

异常处理提案概述了构建一个与宿主环境“良好配合”的概念所涉及的大量复杂性。有趣的是,这是第二次尝试创建这个提案,可见他们目前面临的挑战有多严峻!

该提案不仅要向 WebAssembly 添加异常处理,更是要引入一种更通用的事件概念,看起来很像中断。当事件发生时,执行被暂停,在 events 处安插一个恰当的处理程序。

除了事件,可能还会添加标准的 try/catch 指令:

复制代码
try block_type
instruction*
catch
instruction*
end

这将减少 WebAssembly 编译器的一些复杂性。

垃圾回收

大多数现代编程语言(不包括系统级语言)使用垃圾回收器进行内存管理。简而言之,垃圾回收器(GC)让开发人员无需过多考虑内存管理,他们可以创建对象、传递对象、在函数 / 变量之间共享对象,并且在不再使用这些对象时依靠 GC 来清理它们。

WebAssembly 没有垃圾回收器。事实上,它没有任何可用于内存管理的工具,它只是为你提供了一块“内存”。不使用 GC 的编程语言仍然需要某种机制来管理内存分配,例如 Rust 使用了一个小型的 WebAssembly 优化分配器。

目前,需要垃圾回收器的编程语言没有其他选择,只能将 GC 编译为 wasm,并将其作为二进制文件的一部分,例如 AssemblyScript 就在二进制文件中包含了一个“makeshift GC”。但这样会增加二进制文件的大小,同时 GC 算法的效率也会受到影响。缺少 GC 是 Scala 和 Elm 等语言还不支持编译成 WebAssembly 的原因。

这个提案将 GC 功能带到 WebAssembly 中。有趣的是,它不会有自己的 GC,而是与宿主环境的 GC 集成。还有其它各种其他提案(宿主绑定、引用类型)旨在改进与宿主的互操作性,从而更容易共享状态和调用 API。使用单个 GC 来管理内存会让这些变得更容易。

这个提案是一个重大变更,wasm 的类型系统因此添加了很多新的东西,包括简单的元组、结构体和数组。还有一些讨论是关于添加字符串类型的。

在 WebAssembly 中使用 GC 是可选的,这样 Rust/C++ 就可以使用内存分配器和线性内存。新类型将在新的 WebAssembly 堆上进行分配,尽管提案中未明确说明。我猜宿主堆也可以使用,但可能会带来很大的开销。

这个提案增加了很多新的指令,这是结构体的一个例子:

复制代码
;; structures with fields
(type $point (struct (field $x f64) (field $y f64) (field $z f64)))
 
;; allocated with new
(call $g (new $point (i32.const 1) (i32.const 2) (i32.const 3)))
 
;; field accessors - type checked when validated
(load_field $point $x (get_local $p)

ECMA 模块集成

ECMAScript 模块(ESM)是一个相对较新的规范,所有主流浏览器现在都已支持。

目前,wasm 模块是通过 HTTP 进行加载的,然后使用 JS API 进行实例化:

复制代码
const req = fetch("./myModule.wasm");
 
const instance = await WebAssembly.instantiateStreaming(req)
instance.exports.foo()

这个提案引入了一种机制,可以通过 ESM 导入的方式来加载 wasm 模块:

复制代码
import {foo} from "./myModule.wasm";
foo()

这让实例化 wasm 模块变得更简单,而更大的好处是它们成为 JS 模块图的一部分,也可以进行摇树优化(tree shaking)、捆绑、代码分割和 ESM 支持的其他优化。

批量内存操作

该提案增加了复制 / 填充线性内存区域的新操作。它们将为某些场景带来更好的性能。

尾调用

递归函数调用可能会导致很深的调用栈,会带来各种问题(性能、内存消耗、堆栈溢出的可能性)。通过尾调用优化,递归函数调用将被替换为迭代。这种技术对于函数式语言来说非常重要。为此,该提案引入了新的 return_call 指令。

宿主绑定

基于多种因素(wasm 类型系统太过简单、缺少引用类型等等),WebAssembly 与 JavaScript 宿主之间的当前接口非常有限。如果你想要编写一个操作 DOM 或使用其他浏览器 API 的 wasm 模块,必须编写大量“胶水”代码。

这个提案允许 WebAssembly 模块创建、传递、调用和操作 JavaScript/DOM 对象。它添加了一部分与宿主绑定相关的内容,其中包括用于描述绑定机制或接口的注解。

Rust 已经有了一个工具,叫作 wasm-bindgen,它的作用与该提案很相似。使用 wasm-bindgen,你就可以轻松地跨越 wasm 和 JS 传递字符串等对象。该工具将绑定元数据添加到 wasm 模块中,并生成所需的 JS 胶水代码。

以文本格式自定义注解

wasm 二进制格式支持将元数据添加到模块中。这个提案为文本格式也添加了类似的功能,这对宿主绑定来说非常有用。举个例子:

复制代码
(module
(func (export "f") (param i32 (@js unsigned)) ...)
)

@js unsigned 注解添加了用于生成宿主绑定的其他元数据。

结论

希望这些能让你对 WebAssembly 未来的发展方向有所了解。这些提案中的一些小改进可能很快就能完成,但大的改进可能需要几年时间才能完全实现。

查看英文原文: https://blog.scottlogic.com/2018/07/20/wasm-future.html

感谢覃云对本文的审校。

2018-08-05 09:502485
用户头像

发布了 731 篇内容, 共 461.2 次阅读, 收获喜欢 2004 次。

关注

评论

发布
暂无评论
发现更多内容

作者推荐 | 【深入浅出MySQL】「底层原理」探秘缓冲池的核心奥秘,揭示终极洞察

码界西柚

MySQL 底层原理 缓冲池 Buffer Pool 2024年第二十三篇文章

直播预告|原生 vs 跨端,聊聊鸿蒙应用开发的真实感受

小红书技术REDtech

鸿蒙 前端 开发 跨端开发 小红书

Bartender 4 下载 Mac菜单栏管理 v4.2.25 支持m1 m2

南屿

Bartender 4 Bartender5 Bartender破解版 Mac软件下载站

软件供应链安全继续强化:SBOM清单基座规范SBOMit启动制订

sender_is_sender

软件开发生命周期 软件供应链安全 软件物料清单(SBOM) in-toto

微信Mac版怎么下载安装?含Mac版微信防撤回、多开助手

南屿

微信助手 微信分身

C# 面向对象编程进阶:构造函数详解与访问修饰符应用

小万哥

C# 程序人生 编程语言 软件工程 后端开发

《深入理解Kafka:核心设计与实践原理》PDF

程序员李木子

8个可替代Visio的绘图软件推荐!每一款都堪称神器。

彭宏豪95

效率工具 流程图 在线白板 绘图软件 Visio

好用的截图工具Snagit功能介绍及Snagit中文下载安装

Rose

截图 Snagit下载 Snagit 2023 Snagit截图软件

Turbo Boost Switcher Pro永久激活版 cpu温度检测调节工具 mac软件下载

Rose

苹果电脑 CPU性能 Turbo Boost Switcher Pro cpu频率调节

车内语音识别技术:智能驾驶的革新之源

数据堂

幻兽帕鲁来啦!京东云召唤你一键开服,快来私服联机

京东科技开发者

resolume arena破解版 附安装教程 Mac电脑VJ调试软件 兼容M1

南屿

Mac软件 苹果电脑 Resolume Arena 7破解版 VJ调试 Resolume Arena 安装教程

左耳听风 - 管理方式「读书打卡 day 18」

Java 工程师蔡姬

读书笔记 程序员 个人成长 职业发展 管理方式

车内语音识别技术:智能驾驶的核心要素

数据堂

EMQ 发布MQTT over QUIC 白皮书:下一代车联网消息传输标准协议

新消费日报

premiere pro 2023的字幕功能使用教程 含PR2023中文下载安装包

南屿

PR adobe PR2023中文版 Premiere Pro字幕

《Kafka权威指南》PDF

程序员李木子

eudic欧路词典下载 mac翻译软件 v4.5.9 增强激活版 支持m1 m2

南屿

Mac 翻译软件 欧路词典 Eudic Eudic欧路词典破解版 英汉翻译

车内语音识别技术在智能驾驶中的应用与前景

数据堂

车内语音识别技术:重塑智能驾驶的未来

数据堂

Red Giant Universe 2024破解版 AE红巨星特效插件包for mac 兼容M1/M2

南屿

红巨人特效插件 视频特效插件 Red Giant2024

JProfiler 14 mac永久稳定版 含jprofiler14激活许可 兼容M1/M2

南屿

Java JProfiler Mac永久激活版 JProfiler 14

轻量级UML建模工具 Astah Professional mac注册激活版 附详细安装教程

南屿

UML建模 Astah Professional破解版 astah professional怎么用

Cheetah3D 8:对 Apple Silicon 的原生支持 Metal API 的本机支持

南屿

动画 渲染 3d建模 Cheetah3D注册机 Cheetah3D 8新功能

专业的iOS解锁工具AnyMP4 iPhone Unlocker mac直装免激活版

南屿

Mac软件 iPhone解锁器 iOS解锁 AnyMP4 iPhone

OpenAI又放大招!大幅暴降,修复GPT-4变懒!

鹤涵

WebAssembly的未来:潜在新特性一览_JavaScript_Colin Eberhardt_InfoQ精选文章