Board logo

标题: WebAssembly 现状与实战(1) [打印本页]

作者: look_w    时间: 2018-11-22 19:27     标题: WebAssembly 现状与实战(1)

为什么需要                WebAssembly自从 JavaScript 诞生起到现在已经变成最流行的编程语言,这背后正是 Web 的发展所推动的。Web 应用变得更多更复杂,但这也渐渐暴露出了                JavaScript 的问题:
针对以上两点缺陷,近年来出现了一些 JS 的代替语言,例如:
以上尝试各有优缺点,其中:
三大浏览器巨头分别提出了自己的解决方案,互不兼容,这违背了 Web 的宗旨; 是技术的规范统一让 Web 走到了今天,因此形成一套新的规范去解决 JS                所面临的问题迫在眉睫。
于是 WebAssembly 诞生了,WebAssembly 是一种新的字节码格式,主流浏览器都已经支持 WebAssembly。 和 JS                需要解释执行不同的是,WebAssembly 字节码和底层机器码很相似可快速装载运行,因此性能相对于 JS 解释执行大大提升。 也就是说                WebAssembly 并不是一门编程语言,而是一份字节码标准,需要用高级编程语言编译出字节码放到 WebAssembly 虚拟机中才能运行,                浏览器厂商需要做的就是根据 WebAssembly 规范实现虚拟机。
WebAssembly                原理要搞懂 WebAssembly 的原理,需要先搞懂计算机的运行原理。 电子计算机都是由电子元件组成,为了方便处理电子元件只存在开闭两种状态,对应着 0                和 1,也就是说计算机只认识 0 和 1,数据和逻辑都需要由 0 和 1 表示,也就是可以直接装载到计算机中运行的机器码。                机器码可读性极差,因此人们通过高级语言 C、C++、Rust、Go 等编写再编译成机器码。
由于不同的计算机 CPU 架构不同,机器码标准也有所差别,常见的 CPU 架构包括 x86、AMD64、ARM,                因此在由高级编程语言编译成可自行代码时需要指定目标架构。
WebAssembly 字节码是一种抹平了不同 CPU 架构的机器码,WebAssembly 字节码不能直接在任何一种 CPU 架构上运行,                但由于非常接近机器码,可以非常快的被翻译为对应架构的机器码,因此 WebAssembly 运行速度和机器码接近,这听上去非常像 Java                字节码。
相对于 JS,WebAssembly 有如下优点:
每个高级语言都去实现源码到不同平台的机器码的转换工作是重复的,高级语言只需要生成底层虚拟机(LLVM)认识的中间语言(LLVM IR), 能实现:
除此之外 LLVM 还实现了 LLVM IR 到 WebAssembly 字节码的编译功能,也就是说只要高级语言能转换成 LLVM IR,就能被编译成                WebAssembly 字节码,目前能编译成 WebAssembly 字节码的高级语言有:
通常负责把高级语言翻译到 LLVM IR 的部分叫做编译器前端,把 LLVM IR 编译成各架构 CPU 对应机器码的部分叫做编译器后端;                现在越来越多的高级编程语言选择 LLVM 作为后端,高级语言只需专注于如何提供开发效率更高的语法同时保持翻译到 LLVM IR                的程序执行性能。
编写                WebAssemblyAssemblyScript 初体验接下来详细介绍如何使用 AssemblyScript 来编写 WebAssembly,实现斐波那契序列的计算。 用 TypeScript                实现斐波那契序列计算的模块 f.ts 如下:
1
2
3
4
5
6
export function f(x: i32): i32 {
    if (x === 1 || x === 2) {
        return 1;
    }
    return f(x - 1) + f(x - 2)
}




在按照  成功安装后, 再通过
asc f.ts -o f.wasm




就能把以上代码编译成可运行的 WebAssembly 模块。
为了加载并执行编译出的 f.wasm 模块,需要通过 JS 去加载并调用模块上的 f 函数,为此需要以下 JS 代码:
1
2
3
4
5
6
fetch('f.wasm') // 网络加载 f.wasm 文件
    .then(res => res.arrayBuffer()) // 转成 ArrayBuffer
    .then(WebAssembly.instantiate) // 编译为当前 CPU 架构的机器码 + 实例化
    .then(mod => { // 调用模块实例上的 f 函数计算
    console.log(mod.instance.f(50));
    });




以上代码中出现了一个新的内置类型 i32,这是 AssemblyScript 在 TypeScript 的基础上内置的类型。                AssemblyScript 和 TypeScript 有细微区别,AssemblyScript 是 TypeScript 的子集,为了方便编译成                WebAssembly 在 TypeScript 的基础上加了更严格的 , 区别如下:
总体来说 AssemblyScript 比 TypeScript 又多了很多限制,编写起来会觉得局限性很大; 用 AssemblyScript 来写                WebAssembly 经常会出现 tsc 编译通过但运行 WebAssembly 时出错的情况,这很可能就是你没有遵守以上限制导致的;但                AssemblyScript 通过修改 TypeScript 编译器默认配置能在编译阶段找出大多错误。
AssemblyScript 的实现原理其实也借助了 LLVM,它通过 TypeScript 编译器把 TS 源码解析成 AST,再把 AST 翻译成                IR,再通过 LLVM 编译成 WebAssembly 字节码实现; 上面提到的各种限制都是为了方便把 AST 转换成 LLVM IR。
为什么选 AssemblyScript 作为 WebAssembly 开发语言AssemblyScript 相对于 C、Rust 等其它语言去写 WebAssembly                而言,好处除了对前端来说无额外新语言学习成本外,还有对于不支持 WebAssembly 的浏览器,可以通过 TypeScript                编译器编译成可正常执行的 JS 代码,从而实现从 JS 到 WebAssembly 的平滑迁移。
接入 Webpack                构建任何新的 Web 开发技术都少不了构建流程,为了提供一套流畅的 WebAssembly 开发流程,接下来介绍接入 Webpack 具体步骤。
1. 安装以下依赖,以便让 TS 源码被 AssemblyScript 编译成 WebAssembly。
1
2
3
4
5
6
7
8
9
{
  "devDependencies": {
    "assemblyscript": "github:AssemblyScript/assemblyscript",
    "assemblyscript-typescript-loader": "^1.3.2",
    "typescript": "^2.8.1",
    "webpack": "^3.10.0",
    "webpack-dev-server": "^2.10.1"
  }
}




2. 修改 webpack.config.js,加入 loader:
1
2
3
4
5
6
7
8
9
10
11
12
13
module.exports = {
    module: {
        rules: [
            {
                test: /\.ts$/,
                loader: 'assemblyscript-typescript-loader',
                options: {
                    sourceMap: true,
                }
            }
        ]
    },
};




3. 修改 TypeScript 编译器配置 tsconfig.json,以便让 TypeScript 编译器能支持 AssemblyScript                中引入的内置类型和函数。
1
2
3
4
5
6
{
  "extends": "../../node_modules/assemblyscript/std/portable.json",
  "include": [
    "./**/*.ts"
  ]
}




4. 配置直接继承自 assemblyscript 内置的配置文件。




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0