初探webAssembly | 京东物流技术团队

京东云开发者
• 阅读 336

1 WebAssembly是什么?

一种运行在现代网络浏览器中的新型代码,并且提供新的性能特性和效果

W3C WebAssembly Community Group开发的一项网络标准,对于浏览器而言,WebAssembly 提供了一条途径,让各种语言编写的代码以接近原生的速度在 Web 中运行。在这种情况下,以前无法以此方式运行的客户端软件等都将可以运行在 Web 中。

WebAssembly 设计之初就决定和 JavaScript 一起协同运行——通过JavaScript 中的 WebAssembly API,可以把 WebAssembly 模块加载到一个 JavaScript 应用中并且在两者之间互相调用。这样可以在同一个应用中使用 WebAssembly 的高性能及 JavaScript 的高灵活性。

2 为什么需要WebAssembly?

众所周知JavaScript是解释型语言,相比于编译型语言需要在运行时转换,所以解释型语言的执行速度要慢于编译型语言。

编译型语言和解释型语言代码执行的具体流程如下:

初探webAssembly | 京东物流技术团队

因为解释型语言每次执行都需要把源码转换一次才能执行,而转换过程非常耗费时间和性能,也就导致在JavaScript背景下,web无法执行一些高性能应用,如图片剪辑、视频剪辑、3D游戏等。

根据MDN的定义,WebAssembly是一种运行在现代网络浏览器中的新型代码,并且提供新的性能特性和效果。可以在现代的网络浏览器中运行 - 它是一种低级的类汇编语言,具有紧凑的二进制格式,可以接近原生的性能运行,并为诸如C / C ++等语言提供一个编译目标,以便它们可以在Web上运行。它也被设计为可以与JavaScript共存,允许两者一起工作。

3 WebAssembly的工作原理

WebAssembly不被解释,而是由开发者提前编译为WebAssembly二进制格式,如下图所示。由于变量类型都是预知的,因此浏览器加载WebAssembly文件时,JavaScript引擎无须监测代码。它可以简单地将这段代码的二进制格式编译为机器码。

初探webAssembly | 京东物流技术团队

如果将每种编程语言都直接编译为机器码的各个版本,那么效率会很低。编译器中称为前端的部分会将所编写的代码编译为一种中间表示(intermediate representation,IR)。创建好IR代码后,编译器的后端部分会接收IR代码,对其进行优化,然后将其转换为所需要的机器码。

初探webAssembly | 京东物流技术团队

如果将每种编程语言都直接编译为机器码的各个版本,那么效率会很低。编译器中称为前端的部分会将所编写的代码编译为一种中间表示(intermediate representation,IR)。创建好IR代码后,编译器的后端部分会接收IR代码,对其进行优化,然后将其转换为所需要的机器码。

初探webAssembly | 京东物流技术团队

由于浏览器可以在若干不同的处理器(比如桌面计算机、智能手机和平板设备)上运行,因此为每个可能的处理器发布一个WebAssembly代码的编译后版本会非常繁复。替代方法即取得IR代码,并通过一个专门的编译器来运行,这个编译器将IR代码转换为一种专用字节码并放入后缀为.wasm的文件中。此时wasm文件中的字节码还不是机器码,它只是支持WebAssembly的浏览器能够理解的一组虚拟指令。当加载到支持WebAssembly的浏览器中时,浏览器会验证这个文件的合法性,然后这些字节码会继续编译为浏览器所运行的设备上的机器码。如下图

初探webAssembly | 京东物流技术团队

初探webAssembly | 京东物流技术团队

WebAssembly被设计为JavaScript的一个组件,不是它的替代品。虽然有些开发者试图只用WebAssembly来创建整个网站,但这不是普遍情况。一般情况JavaScript仍然是更好的选择。

4 WebAssembly模块内部

初探webAssembly | 京东物流技术团队

模块中不同段的含义说明:

初探webAssembly | 京东物流技术团队

初探webAssembly | 京东物流技术团队

编译器负责生成WebAssembly模块的段,并将它们按照适当顺序放置。

所有的段都是可选的,因此可能存在空模块。

如果指定了已知段,那么它们只能出现一次并且要按照特定顺序出现。

自定义段可以放置在已知段之前、之间或之后,用于指定不适用已知段的数据。

5 哪些语言可用来创建WebAssembly模块?

现在WebAssembly的最小可行性版本(Minimum Viable Product,MVP)还没有垃圾回收(garbage collection,GC),他限制了一些语言的使用。GC作为一种后MVP功能正在开发中,实现之前,有几种语言正在试验WebAssembly支持,方式是将自己的VM编译到WebAssembly,或者在某些情况下将自己的垃圾回收器包含进去。

以下语言正在试验或已经完成WebAssembly支持:

  • C和C++
  • Rust正致力于成为WebAssembly的首选编程语言。
  • AssemblyScript是一种新编译器,它用来将TypeScript转换为WebAssembly。
  • TeaVM是一个将Java转译到JavaScript的工具,现在也可以生成WebAssembly了。
  • Go 1.11为WebAssembly增加了一个试验性项目,其编译后的WebAssembly模块包含一个垃圾回收器。
  • Pyodide是Python的一个项目,其中包含了Python科学栈的核心包:Numpy、Pandas和matplotlib。
  • Blazor是微软的实验性项目,用于将C#引入WebAssembly。

更多列表关注github: WebAssembly支持列表

相关案例:

TeaVM:它可以将 JVM 字节码翻译成 JavaScript 和 WebAssembly

我们有一段时间后端开始做一些前端开发,但是结果有时并不尽如人意,关键就在于我们的后端开发人员对前端无论是框架还是语法还是规范,都不是非常了解。这是在所难免的,但是因为业务需要又不得不做。

TeaVM就为我们这种情况提供了一种解决方案,我们的后端开发人员依然使用自己熟悉的语言(java)进行开发。功能开发完成后再将.class或.jar文件通过TeaVM编译成wasm或JavaScript供浏览器加载调用。

git:https://github.com/konsoletyper/teavm

官网:https://teavm.org/

6 WebAssembly可以用在哪?

目前大多数浏览器厂商都已经支持WebAssembly,包括Chrome、Edge、Firefox和Safari。移动端Web浏览器也同样支持。Node.js也从版本8开始支持。

WebAssembly不是JavaScript的替代品,而是它的一个补充,有些情况下WebAssembly是更好的选择,有些情况下使用JavaScript会是一个更优的方案。与JavaScript在同一个VM运行可让两种技术相辅相成。

WebAssembly为非JavaScript的开发者提供了一个新的道路,帮助他们在web中使用自己编写的代码。也让不了解C或C++等语言的web开发者可与访问更新、更快的库。个人理解WebAssembly也可用来优化某些库的执行速度。

6.1 一些使用webAssembly的案例

Figma — 基于浏览器的多人实时协作 UI 设计工具:https://www.figma.com/

Google Earth https://earth.google.com/ - 17年开始支持在FireFox打开,主要依赖webAssembly。之前使用Native Client导致只能在chrome中运行

Magnum — 跨平台的 OpenGL 图形引擎https://github.com/mosra/magnum

Egret Engine - 一款HTML5游戏引擎https://github.com/egret-labs/egret-core/

Web-DSP — 使用浏览器就能即时制作多媒体影音特效https://github.com/shamadee/web-dsp

7 WebAssembly怎么用?

7.1 得到wasm文件手动引入

var importObject = {
  imports: {
      imported_func: function(arg) {
        console.log(arg);
      }
    }
  };
  // 输出 42
  fetch('simple.wasm')
  .then(res =>
    res.arrayBuffer()
  ).then(bytes =>
    WebAssembly.instantiate(bytes, importObject)
  ).then(results => {
    results.instance.exports.exported_func();
  });

初探webAssembly | 京东物流技术团队

初探webAssembly | 京东物流技术团队

7.2 得到编译好的npm包引入执行

// alert(`Hello, ${name}`)
const js = import("./node_modules/@jdl/hello-wasm/hello_wasm.js");
js.then(js => {
  js.greet("WebAssembly");
});

初探webAssembly | 京东物流技术团队

以下为hello_wasm.js文件编译前源码

// rust
extern crate wasm_bindgen;

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern {
    pub fn alert(s: &str);
}

#[wasm_bindgen]
pub fn greet(name: &str) {
    alert(&format!("Hello, {}!", name));
}

本文从为什么需要WebAssembly、WebAssembly的工作原理、哪些语言可用来创建WebAssembly模块、WebAssembly可以用在哪里 以及 怎么使用 几方面简要介绍了webAssembly。如果之前没有了解过webAssembly,可以做一些简要的了解。

参考文献

《WebAssembly 实战》 —- C. 杰勒德·加伦特

编译 Rust 为 WebAssembly - WebAssembly | MDN

作者:京东物流 潘维高

来源:京东云开发者社区 自猿其说Tech

点赞
收藏
评论区
推荐文章
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
3年前
Golang modules 初探
今天天色刚刚亮起,起床看到golang1.11正式发版了,有着两个重要的特性:modules和WebAssembly。本博文只要说的是modules,从Java转golang的同学肯定是对golang的包管理充满了无奈之情,我也曾在博客中介绍过glide(https://my.oschina.net/u/553243/blog/1475626),也
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
给 Web 前端工程师看的用 Rust 开发 wasm 组件实战 | 京东云技术团队
什么是wasm组件?wasm全称WebAssembly,是通过虚拟机的方式,可以在服务端、客户端如浏览器等环境执行的二进制程序。他有速度快、效率高、可移植的特点。对我们Web前端工程最大的好处就是可以在浏览器端使用二进制程序处理一些计算量大的处理,使用他比
京东云开发者 京东云开发者
1个月前
JavaScript 与 Rust 和 WebAssembly 集成
作者:京东物流梁瑞乐偶然一次机会,接触了Rust的代码。当时想给团队小伙伴做演示,发现自己并不能在移动端按照文档生成演示demo。我就想,要是Rust代码能转化成JavaScript就好了。结果一搜,还真有。下面整理成文档,分享给大家。为大家解决问题,多提