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

特别说明

这是一个由 simviso 团队对2019 Google I/O 大会中关于面向Web开发人员的WebAssembly相关话题进行翻译的文档,内容并不是直译,其中有一些是译者自身的思考。Surma是Google公司WEB基础的贡献者,也是open web平台的开发倡导者。
上一篇博文地址:面向Web开发人员的WebAssembly 2019 Google I/O 上web

视频地址:面向Web开发人员的WebAssembly 2019 Google I/O 上
视频地址:面向Web开发人员的WebAssembly 2019 Google I/O 下
视频同时也得到了谷歌大佬Surma和Deepti的官方推特分享和点赞
clipboard.png
1.png
视频翻译文字版权归 simviso 全部
3.png
2.pngsegmentfault

前言

如今咱们来谈谈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中引入多线程执行的基础。ide

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

相关文章
相关标签/搜索