WebAssembly入门,未来可期

先来几个名词

解释器

一行行地边解释边执行
复制代码

编译器

是把源代码整个编译成目标代码,执行时不再需要编译器,直接在支持目标代码的平台上运行。
复制代码

解释器的利弊

  • 解释器启动和执行的更快。你不需要等待整个编译过程完成就可以运行你的代码。从第一行开始翻译,就可以依次继续执行了。 正是因为这个原因,解释器看起来更加适合 JavaScript。对于一个 Web 开发人员来讲,能够快速执行代码并看到结果是非常重要的。 这就是为什么最开始的浏览器都是用 JavaScript 解释器的原因。

  • 可是当你运行同样的代码一次以上的时候,解释器的弊处就显现出来了。比如你执行一个循环,那解释器就不得不一次又一次的进行翻译,这是一种效率低下的表现。

编译器的利弊

  • 编译器的问题则恰好相反。 它需要花一些时间对整个源代码进行编译,然后生成目标文件才能在机器上执行。对于有循环的代码执行的很快,因为它不需要重复的去翻译每一次循环。

Just-in-time 及时编译(简称JIT)

为了解决解释器的低效问题,后来的浏览器把编译器也引入进来,形成混合模式。

不同的浏览器实现这一功能的方式不同,不过其基本思想是一致的。在 JavaScript 引擎中增加一个监视器(也叫分析器)。监视器监控着代码的运行情况,记录代码一共运行了多少次、如何运行的等信息。

起初,监视器监视着所有通过解释器的代码。

如果同一行代码运行了几次,这个代码段就被标记成了 “warm”,如果运行了很多次,则被标记成 “hot”。

基线编译器

如果一段代码变成了 “warm”,那么 JIT 就把它送到编译器去编译,并且把编译结果存储起来。如果监视器监视到了执行同样的代码和同样的变量类型,那么就直接把这个已编译的版本 push 出来给浏览器。

优化编译器

如果一个代码段变得 “very hot”,监视器会把它发送到优化编译器中。生成一个更快速和高效的代码版本出来,并且存储之。 更多工作原理介绍请移步 JIT工作原理

JavaScript性能变化曲线

JIT不局限于JS?

JIT总结

简而言之 JIT 是什么呢?它是使 JavaScript 运行更快的一种手段(JIT,内联缓存和隐藏类)之一,通过监视代码的运行状态,把 hot 代码(重复执行多次的代码)进行优化。通过这种方式,可以使 JavaScript 应用的性能提升很多倍。

为了使执行速度变快,JIT 会增加很多多余的开销,这些开销包括:

  • 优化和去优化开销
  • 监视器记录信息对内存的开销
  • 发生去优化情况时恢复信息的记录对内存的开销

各大厂商的方案

  • 微软的 TypeScript 通过为 JS 加入静态类型检查来改进 JS 松散的语法,提升代码健壮性;
  • 谷歌的 Dart 则是为浏览器引入新的虚拟机去直接运行 Dart 程序以提升性能;
  • 火狐的 asm.js 则是取 JS 的子集,JS 引擎针对 asm.js 做性能优化。

以上尝试各有优缺点

  • TypeScript 只是解决了 JS 语法松散的问题,最后还是需要编译成 JS 去运行,对性能没有提升;
  • Dart 只能在 Chrome 预览版中运行,无主流浏览器支持,用 Dart 开发的人不多;
  • asm.js JS语法子集、有很大限制,开发效率低。关于Asm.js的一些基本介绍和它的实现

三大浏览器巨头分别提出了自己的解决方案,互不兼容,这违背了 Web 的宗旨; 是技术的规范统一让 Web走到了今天,因此形成一套新的规范去解决 JS 所面临的问题迫在眉睫。 于是 WebAssembly 诞生了


WebAssembly(Google , Microsoft , Mozilla , Apple 等几家大公司合作发起的)

WebAssembly 是一种新的字节码格式,主流浏览器都已经支持 WebAssembly。 和 JS 需要解释执行不同的是,WebAssembly 字节码和底层机器码很相似可快速装载运行,因此性能相对于 JS 解释执行大大提升。 也就是说 WebAssembly 并不是一门编程语言,而是一份字节码标准,需要用高级编程语言编译出字节码放到 WebAssembly 虚拟机中才能运行.

WebAssembly优点

  • 体积小:由于浏览器运行时只加载编译成的字节码,一样的逻辑比用字符串描述的 JS 文件体积要小很多;
  • 加载快:由于文件体积小,再加上无需解释执行,WebAssembly 能更快的加载并实例化,减少运行前的等待时间;

能编译成 WebAssembly 字节码的高级语言有:

  • AssemblyScript:语法和 TypeScript 一致,对前端来说学习成本低。
  • c\c++:官方推荐的方式
  • Rust:语法复杂、学习成本高,对前端来说可能会不适应。
  • Kotlin:语法和 Java、JS 相似,语言学习成本低。

WebAssembly是如何工作的

使用高级语言来编写WebAssembly模块,将其编译成.wasm文件。这些.wasm文件并不能直接被浏览器识别,所以它们需要一种称为JavaScript胶接代码(glue code,用于连接相互不兼容的组件,详见:http://whatis.techtarget.com/definition/glue-code)的东西来加载。
复制代码

1.Emscripten编译器

C到WebAssembly的编译器,推荐使用Emscripten(https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html),安装这个工具费时费力费空间。
复制代码

有一个在线 C/C++ 转 wasm 的工具: WasmExplorer

JavaScript胶接代

function loadWebAssembly (path) {
  return fetch(path)                   // 加载文件        
    .then(res => res.arrayBuffer())    // 转成 ArrayBuffer
    .then(WebAssembly.instantiate)     // 编译 + 实例化
    .then(mod => mod.instance)         // 提取生成都模块
}
复制代码

其实就是 【加载文件】->【转成 buffer】->【编译】->【实例化】

DEMO C语言到WebAssembly

math.c

int square (int x) {
  return x * x;
}
复制代码

loader.js

见上节JavaScript胶接代

兼容性

各大主流浏览器都已经支持!

案例

  • 在2017年5月时,白鹭引擎宣布开始支持 WebAssembly,而利用 WebAssembly,白鹭引擎可以将 HTML 5 代码编译为机器码运行,让游戏运行性能提升 300%。
  • 2017年10月底,谷歌开始支持让 Google Earth 在 Firefox 上运行,其中的关键就是使用了 WebAssembly。
  • TeaVM 是一个 AOT 编译器(翻译器),可将 Java 字节码翻译成 JavaScript 或 WebAssembly 格式。
  • Blazor — 让 .NET 代码也能在浏览器运行 开源 UI 框架 Blazor 可以让 .NET 代码在浏览器环境中运行,而习惯 ASP.NET Razor 语法的开发者,仍可以继续沿用习惯的开发模式

WebAssembly也许是JS性能的第二个拐点,未来可期

既然编译好后的机器码执行速度很快,为啥浏览器不尝试直接支持编译型语言??

  • JavaScript的历史地位,WebAssembly与其相辅相成.JavaScript巨大的生态系统和友好的语法,WebAssembly接近原生的表现性能。
  • WebAssembly 字节码非常接近机器码,可以非常快的被翻译为对应架构的机器码,因此 WebAssembly 运行速度和机器码接近。
  • 类比Java 字节码
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值