【JSConf EU 2018】Rust + WebAssembly

栏目: 编程语言 · Rust · 发布时间: 6年前

内容简介:在今年的欧洲JSConf上来自Mozilla的Lin Clark为我们展示一个神秘项目,一个的拱形彩虹门(视频传送门),它实际上是由三万个彩色LED组成的画布,可以展现灯光动画,并且通过Rust编写的WebAssembly模块来控制“拱门”的灯光动画。Lin在2017年的JSConf上也曾做过关于WebAssembly的演讲,在该演讲中她提到2008年是JavaScript执行效率曲线的一个拐点,随着众多浏览器加入了JIT编译器(Just-in-time compiler),JavaScript的运行性能

在今年的欧洲JSConf上来自Mozilla的Lin Clark为我们展示一个神秘项目,一个的拱形彩虹门(视频传送门),它实际上是由三万个彩色LED组成的画布,可以展现灯光动画,并且通过Rust编写的WebAssembly模块来控制“拱门”的灯光动画。Lin在2017年的JSConf上也曾做过关于WebAssembly的演讲,在该演讲中她提到2008年是JavaScript执行效率曲线的一个拐点,随着众多浏览器加入了JIT编译器(Just-in-time compiler),JavaScript的运行性能带来了十倍的增速,这为JavaScript插上了一双翅膀使它可以自由翱翔在浏览器端、服务器端和客户端。Lin指出WebAssembly的诞生可能会成为曲线的下一个拐点。可见Mozilla对WebAssembly的重视程度。

【JSConf EU 2018】Rust + WebAssembly

emm...让我们回到2018年。Lin在会上说明了如何使用WebAssembly模块控制“拱门”的灯光动画。下面让我们来看下这是如何做到的。

用字节把空间或时间连续起来

我们所处的空间是一个三维空间,如果再给它加上时间维度,那它就是四维空间。

【JSConf EU 2018】Rust + WebAssembly

计算机是没有办法理解这个四维空间的,如果要让计算机可以“理解”,我们需要对四维空间降维。首先是时间维度,可以通过帧来完成的。显示屏就像一个翻页的书,每一帧就相当于书的一页。

【JSConf EU 2018】Rust + WebAssembly

在web端,60FPS是可以通过屏幕流畅展示动画的要求。这意味着你有60个不同的屏幕快照--一秒时间内60个点的动画定格的样子。可以想象下一连串代表着三维空间的快照。

【JSConf EU 2018】Rust + WebAssembly

现在要从三维降到二维,我们要做的是将空间压平到一个方格纸上。

【JSConf EU 2018】Rust + WebAssembly

现在已经下降到了二维,我们需要再一次降维。把方格纸上面的每一行拿出来按顺序连接起来。

【JSConf EU 2018】Rust + WebAssembly

现在下降到了一行像素,我们已经可以把它放到内存里面了,因为WebAssembly内存(linear memory)基本就是一排小格子。这意味着我们已经下降到一维结构,但是仍然拥有着代表着二维、三维或四维的全部数据。只是现在它们是以一种连续的、线性的方式在展示。

线性内存(Linear memory)

线性内存是JavaScript和WebAssembly的一个主要通信方式,WebAssembly和运行它的JavaScript都可以访问这个对象。线性内存实际上是一个可变大小的ArrayBuffer对象,本质上是连续的、按字节可寻址的一段内存。

【JSConf EU 2018】Rust + WebAssembly

为了使上面提到的“拱门”产生灯光动画,JavaScript告诉WebAssembly模块:“好的,现在就填入动画。”,这一步通过JavaScript调用WebAssembly的function来完成。

【JSConf EU 2018】Rust + WebAssembly

通过WebAssembly为线性内存里的每一个像素填入颜色。

【JSConf EU 2018】Rust + WebAssembly

然后JavaScript代码将获取这些颜色数据并把他们转化成一个JSON数组发送给“拱门”。

【JSConf EU 2018】Rust + WebAssembly

接下来我们来看下如何在JavaScript里使用这些数据。

为线性内存填入颜色

线性内存其实是一大行0和1。如果你想赋予这些0和1意义,那你需要指出如何分割它们。你要做的是为AarryBuffer创建一个TypedArray,告诉JavaScript如何对AarryBuffer里的比特位(bit)行分段。就像正在绘制的格子围绕着这些比特位对它们说那些比特位是属于那些数字。

【JSConf EU 2018】Rust + WebAssembly

例如你用了一个16进制的值,那你的数字将有24位的宽度。所以你需要一个24位的格子。每个格子都包含一个像素,而可容纳24位最小的格子是32位的(int32),所以我们将在这个缓冲区上创建一个Int32Array的视图。它将这段缓冲区的字节码包裹到格子里。在这个例子里我们需要添加一些空白来填充这个格子由24位补齐到32位。

如果我们使用RGB值,这些格子将是8位的宽度。为了得到一个RGB的值,你将使用每三个格子代表你的R、G和B的值。这意味着你需要遍历这些格子,并取出它们里面的数字。

【JSConf EU 2018】Rust + WebAssembly

直接使用线性内存,你需要手动(写一些代码)遍历它,把它里面的数据取出来存放到更加合理的数据结构里。对于这个项目来说,这样做不是很糟糕。颜色的映射是数字,它们相对容易使用线性内存来表示。我们使用的数据结构(RGB值)也不是很复杂。但是如果你使用的是更加复杂的数据结构,直接处理内存将会很痛苦。如果你可以直接传一个JavaScript对象给WebAssembly,让WebAssembly去维护它,这将会变简单很多。你只需要添加一个很小的库(wasm-bindgen)就可以做到这些。

使用wasm-bindgen

wasm-bindgen 是使用Rust写的一个库,它可以使JavaScript与WebAssembly模块之间的数据交互变的更简单。它用一个JavaScript wrapper 来包裹WebAssembly模块。这个wrapper知道如何将复杂的JavaScript对象写入线性内存。然后,当WebAssembly函数返回一个值时,JavaScript wrapper将从线性内存中获取数据并将其重新转换为JavaScript对象。

【JSConf EU 2018】Rust + WebAssembly

要做到这一点,它会查看Rust代码中的函数签名,并计算出所需的JavaScript。这适用于像字符串这样的内置类型,也适用于你定义在代码里的类型。wasm-bindgen将Rust结构体转化JavaScript的类。该 工具 在当前版本只支持Rust,之后会不断完善从而支持其他编程语言(例如:C/C++)。

这个项目是开始学习WebAssembly的很好的开始,因为我们可以通过自己编写的WebAssembly模块来对真实世界产生影响。是不是很酷、很有趣。想体验通过写WebAssembly模块来控制灯光动画的乐趣吗?Mozilla已经帮我们准备了在线环境The Arch,现在就开始体验吧!


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Mission Python

Mission Python

Sean McManus / No Starch Press / 2018-9-18 / GBP 24.99

Launch into coding with Mission Python, a space-themed guide to building a complete computer game in Python. You'll learn programming fundamentals like loops, strings, and lists as you build Escape!, ......一起来看看 《Mission Python》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具