WebAssembly漫游指南

2020-01-09  本文已影响0人  hellomyshadow

WebAssembly 是一种可以使用非 JavaScript 编程语言编写代码并且能在浏览器上运行的技术方案。

解释器与编译器

编程中,通常有两种翻译方法将代码翻译成机器语言:解释器、编译器。

  1. 使用解释器,翻译的过程基本上是一行一行及时生效的;


    解释器.jpg
  2. 编译器是另外一种工作方式,它在执行前翻译。


    编译器.jpg
  3. 每种翻译方法都有利弊
  1. 作为一个可以摆脱解释器低效率的方法,浏览器开始引入编译器。浏览器给JS引擎添加了一个新的部分 -- 监视器(分析器),在JS运行时监控代码,并记录代码片段运行的次数,以及使用的数据类型;
    1. 如果相同的代码块运行了几次,则被标记为warm。如果运行次数比较多,就被标记为hot
    2. warm代码块被扔给基础编译器,只能提升一点点的速度。hot代码块则被扔给优化编译器,速度大大提升。

性能瓶颈

要了解WebAssembly,首先要了解JS引擎的工作原理 ---明确一点,JS没有强制类型约束!

JS引擎.jpg

在项目运行的过程中,引擎会对执行次数较多的 function 记性优化,其代码将编译成Machine Code后打包送到顶部的Just-In-Time(JIT) Compiler(即时编译器),下次再执行这个function,就会直接执行编译好的Machine Code。但是由于JavaScript的动态变量,上一秒可能是Array,下一秒就变成了Object。那么上一次引擎所做的优化,就失去了作用,此时又要再一次进行优化。

asm.js

为了解决这个问题,WebAssembly的前身,asm.js诞生了。asm.js是一个Javascript的严格子集,合理合法的asm.js代码一定是合理合法的JavaScript代码,反之就不成立。同WebAssembly一样,asm.js不是用来一行一行写代码的,asm.js是一个编译目标。它的可读性、可读性虽然比WebAssembly好,但对开发者来说,仍然是无法接受的。

asm.js 的静态类型约束
    function asmJs() {
        'use asm';
        
        let myInt = 0 | 0;
        let myDouble = +1.1;
    }

看似问题解决了,但不管asm.js对静态类型做得再好,它始终逃不过Parser --> ByteCode Compiler,它们是JavaScript代码在引擎执行过程当中消耗时间最多的两步。而WebAssembly不用经过这两步。这就是WebAssemblyasm.js更快的原因。

WebAssembly

在2015年,WebAssembly横空出世。WebAssembly是经过编译器编译之后的代码,体积小、起步快。在语法上完全脱离JavaScript,同时具有沙盒化的执行环境。WebAssembly同样的强制静态类型,是C/C++/Rust的编译目标。

JavaScript vs WebAssembly

  1. 目前JIT编译器在浏览器中很常见,JS引擎运行一个程序花费的时间
    JS耗时过程 .jpg
  1. 运行一个WebAssembly程序花费的时间
    WebAssembly耗时过程.jpg

WebAssembly如何工作

  1. 不同的机器架构有自己独特的汇编语言,也就是说每一种汇编语言都对应特性的机器架构;
  2. 我们也可以把WebAssembly当做是另外一种目标汇编语言,当我们的代码运行在用户机器的 web 平台上时,我们根本不可能知道用户机器的架构。
    WebAssembly与别的汇编语言不同,它是一个概念机上的机器语言,而不是在一个真正存在的物理机上运行的机器语言,这一点非常重要!
    正因如此,WebAssembly指令有时又被称为虚拟指令,它比JavaScript代码更快更直接的转换成机器代码,但又不直接与特定硬件的特定机器代码对应。
  3. WebAssembly被编译到 .wasm 文件,在浏览器下载后,能迅速转换成目标机器的汇编代码。

使用场景

开发工具

上一篇 下一篇

猜你喜欢

热点阅读