WebAssembly漫游指南

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

解释器与编译器

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

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


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


    编译器.jpg
  3. 每种翻译方法都有利弊
  • 解释器很快的获取代码并且执行。不需要在可以执行代码的时候知道全部的编译步骤。因此,解释器感觉与 JavaScript 有着自然的契合。web开发者能够立即得到反馈很重要。
    这也是浏览器最开始使用 JavaScript 解释器的原因之一。
    但使用解释器的弊端是,当运行相同的代码时,如执行一个循环。那就会一遍又一遍的做同样的事情!
  • 编译器则有相反的效果。在程序开始执行时,它可能需要稍微多一点的时间来了解整个编译的步骤,但当运行一个循环时会更快,因为它不需要重复地去翻译每一次循环里的代码。
  1. 作为一个可以摆脱解释器低效率的方法,浏览器开始引入编译器。浏览器给JS引擎添加了一个新的部分 -- 监视器(分析器),在JS运行时监控代码,并记录代码片段运行的次数,以及使用的数据类型;
    1. 如果相同的代码块运行了几次,则被标记为warm。如果运行次数比较多,就被标记为hot
    2. warm代码块被扔给基础编译器,只能提升一点点的速度。hot代码块则被扔给优化编译器,速度大大提升。

性能瓶颈

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

JS引擎.jpg

  • JavaScript文件会被下载下来
  • 然后进入ParserParser会把代码转化成AST(抽象语法树)
  • 然后根据抽象语法树,Bytecode Compiler字节码编译器会生成引擎能够直接阅读、执行的字节码
  • 字节码进入翻译器,将字节码一行一行的翻译成效率十分高的Machine Code

在项目运行的过程中,引擎会对执行次数较多的 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
  • Parse 源码转换成解释器可以运行的代码;
  • Compiling + optimizing 花费在基础编译和优化编译上的时间。有一些优化编译的工作不在主线程,这里不包括这些时间;
  • Re-optimizing 当预先编译优化的代码不能被优化的情况下,JIT 将这些代码重新优化,如果不能重新优化,则丢给基础编译去做,这个过程叫做重新优化;
  • Execution 执行代码的过程;
  • Garbage Collection(GC) 清理内存的时间。
  1. 运行一个WebAssembly程序花费的时间
    WebAssembly耗时过程.jpg
  • request -> download 图上面并没有展示从服务器上下载所消耗的时间,WebAssembly 设计的体积更小,可以以二进制形式表示,所以下载执行与 JavaScript 等效的 WebAssembly 文件需要更少的时间;
    即使使用 gzip 压缩的 JavaScript 文件很小,但 WebAssembly 中的等效代码可能更小,在网速慢的情况下更能显示出效果来。
  • Parse -> decode JS源码一旦被下载到浏览器,将被解析为抽象语法树(AST);通常浏览器解析源码是惰性的,浏览器首先会解析它们真正需要的东西,没有及时被调用的函数只会被创建成存根。
    在这个过程中,AST被转换为该 JS 引擎的中间表示(称为字节码)。
    相反,WebAssembly 不需要被转换(Parse),因为它已经是目标代码(字节码)了,仅仅需要被解码(decode)并确定没有任何错误。
  • Compiling + optimizing 如前所述,JavaScript是在执行代码期间编译的。因为JavaScript是动态类型语言,相同的代码在多次执行中都有可能都因为代码里含有不同的类型数据被重新编译,这样会消耗时间。
    WebAssembly与机器代码更接近,编译器不需要在运行代码时花费时间去观察代码中的数据类型,在开始编译时做优化,更多的优化在 LLVM 最前面就已经完成了,所以编译和优化的工作很少。
  • Re-optimizing 有时 JIT 抛出一个优化版本的代码,然后重新优化。JIT 基于运行代码的假设不正确时,会发生这种情况。例如,当进入循环的变量与先前的迭代不同时,或者在原型链中插入新函数时,会发生重新优化。
    WebAssembly 中,类型是明确的,因此 JIT 不需要根据运行时收集的数据对类型进行假设。也就是说,WebAssembly 不需要重新优化的周期。
  • Execution 想要编写执行性能好的JavaScript,就需要知道JIT是如何做优化的;然而大多数开发者并不知道 JIT 的内部原理,即使是那些了解 JIT 内部原理的开发人员,也很难实现最佳方案。有很多时候,开发者为了使他们的代码更易于阅读会阻碍编译器优化代码。
    也正因如此,执行 WebAssembly 代码通常更快,有些必须对JavaScript做的优化不需要用在WebAssembly 上。另外,WebAssembly是为编译器设计的,它是目标程序,专门给编译器来阅读,并不是当做编程语言让程序员去写的。
    由于程序员不需要直接编程,WebAssembly提供了一组更适合机器的指令,根据程序代码所做的工作,这些指令的运行速度可以在10%800%之间。
  • GC 在 JavaScript 中,JS 引擎使用垃圾回收器来自动进行垃圾回收处理,这对于控制性能可能并不是一件好事。开发者不能控制垃圾回收的时机,所以它可能在非常重要的时间去工作,从而影响性能。
    WebAssembly根本不支持垃圾回收,内存是手动管理的(就像 C/C++),虽然可能让编程更困难,但确实提升了性能。
  • 总而言之,这些都是在许多情况下,在执行相同任务时WebAssembly将胜过JavaScript的原因。
    甚至在某些情况下,WebAssembly 不能像预期的那样执行,还有一些更改使其更快。

WebAssembly如何工作

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

使用场景

  • 对性能有很高要求的App/Module/游戏
  • 在Web中调用C/C++/Rust/Go的库

开发工具

  • AssemblyScript 支持直接将TypeScript编译成WebAssembly,入门的门槛低。
  • Emscripten 可以说是WebAssembly的灵魂工具,上面说了很多编译,这个就是那个编译器,将其他的高级语言,编译成WebAssembly
  • WABT 是个将WebAssembly在字节码和文本格式相互转换的一个工具,方便开发者去理解wasm到底是在做什么事。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • Javascript ,也叫Ecma script, 是这家伙用了 10 天时间赶出来的。。 所以,各位程序猿们...
    自度君阅读 2,154评论 1 7
  • (图片来源:giphy.com) 编者按:本文由明非在众成翻译平台上翻译。 最近,WebAssembly 在 Ja...
    a6217200e10d阅读 268,251评论 44 303
  • 1、WebAssembly是什么? WebAssembly 是一种低级的类汇编语言,具有紧凑的二进制格式,可以接近...
    前端小钱阅读 2,167评论 0 0
  • 昨天晚上看到凌晨把一个人的朝圣看完了,这本书让我感触挺深的,一个身材高大的老人走过87天,600多英里,最终到达好...
    有点冷清的文艺范阅读 237评论 0 1
  • 2018年7月18日中午一点到两点半,我家在挪空调。当格力工作人员联系我的时候,我很吃惊,天外火辣辣的,简...
    我为云朵阅读 199评论 0 0