「2019 Google I/O 大会」面向Web开发人员的WebAssembly (下)

特别说明

这是一个由 simviso 团队对2019 Google I/O 大会中关于面向Web开发人员的WebAssembly相关话题进行翻译的文档,内容并非直译,其中有一些是译者自身的思考。Surma是Google公司WEB基础的贡献者,也是open web平台的开发倡导者。
视频地址:面向Web开发人员的WebAssembly 2019 Google I/O 下
视频同时也获得了谷歌大佬Deepti的官方推特点赞
1.png
视频翻译文字版权归 simviso 所有
3.png
2.png

前言

现在我们来谈谈WebAssembly的未来和即将到来的未来。欢迎Deepti上台发言。

谢谢,Surma。

Hi,各位,我叫Deepti。我是Chrome团队的软件工程师,我致力于标准化 WebAssembly 功能,并在V8中实现它们。

到目前为止,你在本演讲中所看到的大部分内容都已经在所有主要浏览器中落地实现了。也可以说这是MVP或者说是WebAssembly的最小可行性产品。(译者注:MVP(Minimum Viable Product –最简化可实性产品)是一种在创业团队中非常流行和实用的产品理念,旨在通过提供最小化可行产品获取用户反馈,并在这个最小化可行产品上持续快速迭代,直到产品到达一个相对稳定的阶段。)

并且,我们一直在努力增加功能,以确保我们越来越接近本地性能。这个MVP本身就是打破了Web平台的限制,可以在它之上运行的一整套新的应用程序。但这不是最终目标,社区组织和实现者正在努力实现很多令人兴奋的新功能。

WebAssembly多线程提案

其中第一个就是WebAssembly 多线程提案。多线程提案引入了并行计算。
4.png
具体的说,这意味着它引入了线程之间共享线性内存的概念,以及原子指令的语义。现在,为什么有必要这么做?

有许多用C或C ++编写的现有库使用了Pthreads(POSIX线程(POSIX threads)),它们可以编译成wasm,并且以多线程模式运行,允许不同线程并行处理相同的数据。除了启用新功能外,对于受益于多线程执行的应用程序,你会看到性能随着线程数的增加而增长。因此,这个线程提案是建立在Web平台中已经支持多线程的基础之上。
5.png
Web 已经支持使用Web Workers来进行多线程执行,这刚好可以用来作为在WebAssembly中引入多线程执行的基础。

Web Workers的缺点是他们之间不能共享可变数据。反而,他们依赖消息传递,通过发送消息进行通信。因此它们通过消息传递进行通信。所以每一个WebAssembly线程都在一个Web Worker中运行。

但是它们共享了WebAssembly 内存允许他们处理相同的数据。使它们的运行速度接近于本地速度。

这里的共享线性内存建立在JS共享数组Buffer上。

因此,如果你看这幅图,发现它们每个线程都运行在一个Web Worker中,并且使用一样的线性存储实例化一个WebAssembly 实例。

这意味着这些线程实例的操作可以在共享内存上进行,但各自都有它们自己的独立执行堆栈。因此,用于创建WebAssembly 内存的API几乎保持不变。
6.png
如果你看到图中第一行代码,你创建一个包含 shared 和 maximum 参数的WebAssembly 内存。这将在下面创建一个共享数组Buffer,其中 initial (初始)大小是由我们指定的,即一页内存。

因此,这些线程都在同一个内存上操作,我们怎么确保数据是一致的?

原子修改允许我们执行某种级别的同步。所以,当一个线程执行原子操作时,其他线程在它发生的瞬间会立即看到。但实际上完全同步的操作往往会阻塞一个线程,直到其他线程完成执行。

所以这个提案有一个互斥实现的例子,并且我介绍了如何通过JavaScript使用它。

如果你仔细观察,你会发现你在工作中所做的与在主线程上所做的之间所存在微妙的差异。

因此,在主线程上调用 tryLockMutex 方法,该方法尝试在给定address上添加一把互斥锁 。如果互斥锁锁定成功,则返回1,否则返回0。在工作线程上,它会在给定地址进行互斥锁的锁定,重试直到锁定成功。所以基本在Web上就是通过这样一种方式来构建的(线程模型)。

实际上你不能阻塞主线程。这是我们在使用线程过程中需要记住的,这很有用。那么该提案 现在处于一个什么状态?该提案一直在稳定推进中。

当下正在进行的工作是确定共享数据Buffer使用的内存模型。
7.png
真正让我兴奋的是它已经在 Chrome 74中进行提供,默认情况下是启用状态。Surma 在之前的演讲中提到了QT,并且QT有完整的线程支持,因此你可以在你的应用程序中基于多线程使用它。对于此处来说,这里的共享内存使用的是JavaScript 下的共享数组Buffer。但在某些浏览器上是临时禁用的。

默认情况下,所有浏览器上的WebAssembly多线程目前都无法使用。但你仍然可以在Firefox Nightly版上试试这个。
8.png
WebAssembly 的目标之一是对现代硬件进行低级抽象。对于 WebAssembly SIMD 提案更是如此。

SIMD 是一个单指令多数据流。它允许一条指令同时操作多个数据项。因此,大多数现代CPU都支持矢量运算的某些子集。因此,该提案正尝试利用你每天使用的硬件中已经存在的功能。

这里的挑战是找到一个在大多数架构中都能得到良好支持的子集,但仍在寻找过程中。

目前,该子集仅限于128位SIMD。有两种不同方式去使用SIMD提案。

通过使用自动矢量化,你可以在编译时传入一个标志位来启用SIMD,并且编译器会自动识别你的程序。

另一方面,很多SIMD用例都比较小众,即为了高度专注性能使用手动编写assembly。

所以,这些将会使用Clang内置或内联函数生成针对性能调优的机器码。(译者注:Clang是一个C语言、C++、Objective-C语言的轻量级编译器)

现在,SIMD可用于各种各样的应用程序。所以你可以用它来制作图像或音频,视频编解码器,像Google Earth和Photoshop这样的应用程序,甚至是Web上的机器学习应用程序。

WebML与SIMD

我们对WebML(Web建模语言)和SIMD的协作也很感兴趣。

那么让我们来仔细看看这些数据是如何运作的。
9.png
在这里,你可以看到一个关于数组add指令的简单示例。

假设这是一个Integer类型的数组,在左侧,看起来像是标量运算,将每个数字与另一个数字相加并存储结果。这个矢量版本只能归结为一条硬件指令。(译者注:从图中可以看到有箭头方向)例如,在一些Intel架构上的一个p AD或一个vp AD 操作。

因此,SIMD操作通过允许将多块数据打包到一个数据域中来工作,并且使指令能够作用于每个数据块。

这对于必须对大量数据执行相同操作的情况很有用。

例如,图片处理。如果你想在Squoosh中压缩图片,或者将Photoshop 中图片的色彩降低一半。实际上,SIMD操作在做这些事情时性能会更高。
10.png
我们已经讨论了关于利用底层硬件功能来提升OA办公应用程序的性能。现在,让我们来看看另一方面会发生什么。那么我们该如何更好地与主机交互呢?

引用类型提案

其中一个提议是引用类型提案,由多个浏览器实现。对于引用类型提案,WebAssembly 代码可以使用ref值类型传递任意的JavaScript 值。这些值对WebAssembly不具备透明性,但通过导入JavaScript 内置函数,WebAssembly 模块可以执行许多基本的JavaScript 操作,而无须本来需要的JavaScript 胶水代码。

所以,WebAssembly 表对象是一个高级别存储函数引用的结构。所以这个引用类型提议也添加了一些用于操作wasm内表的表指令。关于这一点的巧妙之处在于,引用类型提案实际上为未来真正有用的提案奠定了基础。

基于此,可以通过Web IDL(接口定义语言)提案更高效的与本地主机进行交互操作或者异常引用的处理。同时它还可以实现更平滑的垃圾回收路径,我将在接下来的几张幻灯片中讨论这些。

WebIDL绑定提案

因此,我们团队在不久的将来会侧重于一个Web IDL绑定提案(译者注:后面有图,一看便知)

Web IDL 是一个接口定义语言,它可以用来定义在Web中实现的接口。

我们通过引用类型来稍微谈下这个,这里的基本思路是,该提案描述了向WebAssembly 添加一个新机制,为了避免在调用或者通过调用Web IDL接口时产生不必要的开销。

Web IDL 提案将会允许编译器优化从WebAssembly到现有的Web API和浏览器环境以及未来可能会用Web IDL 的其他API的调用。

让我们仔细看下这张图。

11.png
当你有一个wasm函数时,你将会通过JS API调用JavaScript 。

JS API通过绑定层来促成JS API与用于Dom访问的Web API之间的通信,这里增加了许多胶水代码和额外开销。

Web IDL绑定提案的目标就是减少这种开销,并优化从WebAssembly到现有的Web API的调用。
12.png
所以实际上,这里不需要通过JS API,并且绑定也将被优化用以减少开销。
13.gif
因此,你可以精简WebAssembly 和 Web API之间调用。

目前,我们谈到了C,C++,Rust,将这些语言放到WebAssembly 上时,都得到了非常好的支持。而且有很多工作会不断地需要将不同种类的其他语言引入Web中来。

WebAssembly的发展与未来

14.png
一旦对支持高级语言必须的垃圾回收功能得以实现,也就意味着更快的执行,更小的模块。

除C,C++之外,这实际上能够支持大多数现代语言的要求。

当然,这也是个巨大的开放性问题。但是我们一直通过制定较小的提案并进行精确的设计约束磨练探索,以此来取得进展。

因此,目前,wasm被明确地设计用于位尾调用优化。将来,我们希望为需要尾调用仿真(系统API,参考前面的分享)的语言启用正确有效的尾调用实现。

所以这些就像是Haskell这样的函数式语言。

V8已经实现了这个,并且进展得十分顺利。因此,对于完整的C++支持,我们需要异常处理。

在Web环境中,异常处理可以使用JavaScript进行模拟。

JavaScript可以为异常处理提供正确的语义,但它的确不快。

因此发布MVP后,WebAssembly 将会获得0成本的异常处理支持,这也是我们正在努力做的事。

我们也在研究一些其他提案,所以请随时查看在 WebAssembly GitHub页面上的未来特性文档。

我要强调的另一件事就是其中有很多都还在设计阶段,如果你有兴趣参与,所有的开发都是在一个开放的社区小组中完成的,因此,随时欢迎贡献。

我们也会讨论性能。如果你有性能瓶颈,并且使用了wasm 去提升了其中一些我们所关注的点,我们会很高兴听取你的意见。

好了,Surma和我就讲到这里。之后我们会在Web Sandbox继续。因此,如果你有问题,请过来找我们或者在网上找我们。

联系我们

欢迎加群和我们交流
16.png
如果感兴趣可以关注我们的微信公众号
17.png

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章