WebAssembly漫游指南

WebAssembly 是一種可以使用非 JavaScript 編程語言編寫代碼并且能在瀏覽器上運(yùn)行的技術(shù)方案贫导。

解釋器與編譯器

編程中的止,通常有兩種翻譯方法將代碼翻譯成機(jī)器語言:解釋器伦泥、編譯器柜候。

  1. 使用解釋器明场,翻譯的過程基本上是一行一行及時(shí)生效的否过;


    解釋器.jpg
  2. 編譯器是另外一種工作方式午笛,它在執(zhí)行前翻譯。


    編譯器.jpg
  3. 每種翻譯方法都有利弊
  • 解釋器很快的獲取代碼并且執(zhí)行苗桂。不需要在可以執(zhí)行代碼的時(shí)候知道全部的編譯步驟药磺。因此,解釋器感覺與 JavaScript 有著自然的契合煤伟。web開發(fā)者能夠立即得到反饋很重要癌佩。
    這也是瀏覽器最開始使用 JavaScript 解釋器的原因之一。
    但使用解釋器的弊端是便锨,當(dāng)運(yùn)行相同的代碼時(shí)围辙,如執(zhí)行一個(gè)循環(huán)。那就會(huì)一遍又一遍的做同樣的事情鸿秆!
  • 編譯器則有相反的效果酌畜。在程序開始執(zhí)行時(shí),它可能需要稍微多一點(diǎn)的時(shí)間來了解整個(gè)編譯的步驟卿叽,但當(dāng)運(yùn)行一個(gè)循環(huán)時(shí)會(huì)更快桥胞,因?yàn)樗恍枰貜?fù)地去翻譯每一次循環(huán)里的代碼。
  1. 作為一個(gè)可以擺脫解釋器低效率的方法考婴,瀏覽器開始引入編譯器贩虾。瀏覽器給JS引擎添加了一個(gè)新的部分 -- 監(jiān)視器(分析器),在JS運(yùn)行時(shí)監(jiān)控代碼沥阱,并記錄代碼片段運(yùn)行的次數(shù)缎罢,以及使用的數(shù)據(jù)類型;
    1. 如果相同的代碼塊運(yùn)行了幾次考杉,則被標(biāo)記為warm策精。如果運(yùn)行次數(shù)比較多,就被標(biāo)記為hot崇棠。
    2. warm代碼塊被扔給基礎(chǔ)編譯器咽袜,只能提升一點(diǎn)點(diǎn)的速度。hot代碼塊則被扔給優(yōu)化編譯器枕稀,速度大大提升询刹。

性能瓶頸

要了解WebAssembly谜嫉,首先要了解JS引擎的工作原理 ---明確一點(diǎn),JS沒有強(qiáng)制類型約束凹联!

JS引擎.jpg

  • JavaScript文件會(huì)被下載下來
  • 然后進(jìn)入Parser沐兰,Parser會(huì)把代碼轉(zhuǎn)化成AST(抽象語法樹)
  • 然后根據(jù)抽象語法樹,Bytecode Compiler字節(jié)碼編譯器會(huì)生成引擎能夠直接閱讀蔽挠、執(zhí)行的字節(jié)碼
  • 字節(jié)碼進(jìn)入翻譯器住闯,將字節(jié)碼一行一行的翻譯成效率十分高的Machine Code

在項(xiàng)目運(yùn)行的過程中,引擎會(huì)對(duì)執(zhí)行次數(shù)較多的 function 記性優(yōu)化象泵,其代碼將編譯成Machine Code后打包送到頂部的Just-In-Time(JIT) Compiler(即時(shí)編譯器)寞秃,下次再執(zhí)行這個(gè)function,就會(huì)直接執(zhí)行編譯好的Machine Code偶惠。但是由于JavaScript的動(dòng)態(tài)變量春寿,上一秒可能是Array,下一秒就變成了Object忽孽。那么上一次引擎所做的優(yōu)化绑改,就失去了作用,此時(shí)又要再一次進(jìn)行優(yōu)化兄一。

asm.js

為了解決這個(gè)問題厘线,WebAssembly的前身,asm.js誕生了出革。asm.js是一個(gè)Javascript的嚴(yán)格子集造壮,合理合法的asm.js代碼一定是合理合法的JavaScript代碼,反之就不成立骂束。同WebAssembly一樣耳璧,asm.js不是用來一行一行寫代碼的,asm.js是一個(gè)編譯目標(biāo)展箱。它的可讀性旨枯、可讀性雖然比WebAssembly好,但對(duì)開發(fā)者來說混驰,仍然是無法接受的攀隔。

asm.js 的靜態(tài)類型約束
    function asmJs() {
        'use asm';
        
        let myInt = 0 | 0;
        let myDouble = +1.1;
    }

看似問題解決了,但不管asm.js對(duì)靜態(tài)類型做得再好栖榨,它始終逃不過Parser --> ByteCode Compiler昆汹,它們是JavaScript代碼在引擎執(zhí)行過程當(dāng)中消耗時(shí)間最多的兩步。而WebAssembly不用經(jīng)過這兩步婴栽。這就是WebAssemblyasm.js更快的原因满粗。

WebAssembly

在2015年,WebAssembly橫空出世居夹。WebAssembly是經(jīng)過編譯器編譯之后的代碼败潦,體積小、起步快准脂。在語法上完全脫離JavaScript劫扒,同時(shí)具有沙盒化的執(zhí)行環(huán)境。WebAssembly同樣的強(qiáng)制靜態(tài)類型狸膏,是C/C++/Rust的編譯目標(biāo)。

JavaScript vs WebAssembly

  1. 目前JIT編譯器在瀏覽器中很常見,JS引擎運(yùn)行一個(gè)程序花費(fèi)的時(shí)間
    JS耗時(shí)過程 .jpg
  • Parse 源碼轉(zhuǎn)換成解釋器可以運(yùn)行的代碼虎眨;
  • Compiling + optimizing 花費(fèi)在基礎(chǔ)編譯和優(yōu)化編譯上的時(shí)間叮姑。有一些優(yōu)化編譯的工作不在主線程,這里不包括這些時(shí)間砾脑;
  • Re-optimizing 當(dāng)預(yù)先編譯優(yōu)化的代碼不能被優(yōu)化的情況下幼驶,JIT 將這些代碼重新優(yōu)化,如果不能重新優(yōu)化韧衣,則丟給基礎(chǔ)編譯去做盅藻,這個(gè)過程叫做重新優(yōu)化;
  • Execution 執(zhí)行代碼的過程畅铭;
  • Garbage Collection(GC) 清理內(nèi)存的時(shí)間氏淑。
  1. 運(yùn)行一個(gè)WebAssembly程序花費(fèi)的時(shí)間
    WebAssembly耗時(shí)過程.jpg
  • request -> download 圖上面并沒有展示從服務(wù)器上下載所消耗的時(shí)間,WebAssembly 設(shè)計(jì)的體積更小硕噩,可以以二進(jìn)制形式表示假残,所以下載執(zhí)行與 JavaScript 等效的 WebAssembly 文件需要更少的時(shí)間;
    即使使用 gzip 壓縮的 JavaScript 文件很小炉擅,但 WebAssembly 中的等效代碼可能更小辉懒,在網(wǎng)速慢的情況下更能顯示出效果來。
  • Parse -> decode JS源碼一旦被下載到瀏覽器坑资,將被解析為抽象語法樹(AST)耗帕;通常瀏覽器解析源碼是惰性的,瀏覽器首先會(huì)解析它們真正需要的東西袱贮,沒有及時(shí)被調(diào)用的函數(shù)只會(huì)被創(chuàng)建成存根仿便。
    在這個(gè)過程中,AST被轉(zhuǎn)換為該 JS 引擎的中間表示(稱為字節(jié)碼)攒巍。
    相反嗽仪,WebAssembly 不需要被轉(zhuǎn)換(Parse),因?yàn)樗呀?jīng)是目標(biāo)代碼(字節(jié)碼)了柒莉,僅僅需要被解碼(decode)并確定沒有任何錯(cuò)誤闻坚。
  • Compiling + optimizing 如前所述,JavaScript是在執(zhí)行代碼期間編譯的兢孝。因?yàn)?code>JavaScript是動(dòng)態(tài)類型語言窿凤,相同的代碼在多次執(zhí)行中都有可能都因?yàn)榇a里含有不同的類型數(shù)據(jù)被重新編譯仅偎,這樣會(huì)消耗時(shí)間。
    WebAssembly與機(jī)器代碼更接近雳殊,編譯器不需要在運(yùn)行代碼時(shí)花費(fèi)時(shí)間去觀察代碼中的數(shù)據(jù)類型橘沥,在開始編譯時(shí)做優(yōu)化,更多的優(yōu)化在 LLVM 最前面就已經(jīng)完成了夯秃,所以編譯和優(yōu)化的工作很少座咆。
  • Re-optimizing 有時(shí) JIT 拋出一個(gè)優(yōu)化版本的代碼,然后重新優(yōu)化仓洼。JIT 基于運(yùn)行代碼的假設(shè)不正確時(shí)介陶,會(huì)發(fā)生這種情況。例如色建,當(dāng)進(jìn)入循環(huán)的變量與先前的迭代不同時(shí)哺呜,或者在原型鏈中插入新函數(shù)時(shí),會(huì)發(fā)生重新優(yōu)化箕戳。
    WebAssembly 中弦牡,類型是明確的,因此 JIT 不需要根據(jù)運(yùn)行時(shí)收集的數(shù)據(jù)對(duì)類型進(jìn)行假設(shè)漂羊。也就是說驾锰,WebAssembly 不需要重新優(yōu)化的周期。
  • Execution 想要編寫執(zhí)行性能好的JavaScript走越,就需要知道JIT是如何做優(yōu)化的椭豫;然而大多數(shù)開發(fā)者并不知道 JIT 的內(nèi)部原理,即使是那些了解 JIT 內(nèi)部原理的開發(fā)人員旨指,也很難實(shí)現(xiàn)最佳方案赏酥。有很多時(shí)候,開發(fā)者為了使他們的代碼更易于閱讀會(huì)阻礙編譯器優(yōu)化代碼谆构。
    也正因如此裸扶,執(zhí)行 WebAssembly 代碼通常更快,有些必須對(duì)JavaScript做的優(yōu)化不需要用在WebAssembly 上搬素。另外呵晨,WebAssembly是為編譯器設(shè)計(jì)的,它是目標(biāo)程序熬尺,專門給編譯器來閱讀摸屠,并不是當(dāng)做編程語言讓程序員去寫的。
    由于程序員不需要直接編程粱哼,WebAssembly提供了一組更適合機(jī)器的指令季二,根據(jù)程序代碼所做的工作,這些指令的運(yùn)行速度可以在10%800%之間。
  • GC 在 JavaScript 中胯舷,JS 引擎使用垃圾回收器來自動(dòng)進(jìn)行垃圾回收處理刻蚯,這對(duì)于控制性能可能并不是一件好事。開發(fā)者不能控制垃圾回收的時(shí)機(jī)桑嘶,所以它可能在非常重要的時(shí)間去工作芦倒,從而影響性能。
    WebAssembly根本不支持垃圾回收不翩,內(nèi)存是手動(dòng)管理的(就像 C/C++),雖然可能讓編程更困難麻裳,但確實(shí)提升了性能口蝠。
  • 總而言之,這些都是在許多情況下津坑,在執(zhí)行相同任務(wù)時(shí)WebAssembly將勝過JavaScript的原因妙蔗。
    甚至在某些情況下,WebAssembly 不能像預(yù)期的那樣執(zhí)行疆瑰,還有一些更改使其更快眉反。

WebAssembly如何工作

  1. 不同的機(jī)器架構(gòu)有自己獨(dú)特的匯編語言,也就是說每一種匯編語言都對(duì)應(yīng)特性的機(jī)器架構(gòu)穆役;
  2. 我們也可以把WebAssembly當(dāng)做是另外一種目標(biāo)匯編語言寸五,當(dāng)我們的代碼運(yùn)行在用戶機(jī)器的 web 平臺(tái)上時(shí),我們根本不可能知道用戶機(jī)器的架構(gòu)耿币。
    WebAssembly與別的匯編語言不同梳杏,它是一個(gè)概念機(jī)上的機(jī)器語言,而不是在一個(gè)真正存在的物理機(jī)上運(yùn)行的機(jī)器語言淹接,這一點(diǎn)非常重要十性!
    正因如此,WebAssembly指令有時(shí)又被稱為虛擬指令塑悼,它比JavaScript代碼更快更直接的轉(zhuǎn)換成機(jī)器代碼劲适,但又不直接與特定硬件的特定機(jī)器代碼對(duì)應(yīng)。
  3. WebAssembly被編譯到 .wasm 文件厢蒜,在瀏覽器下載后霞势,能迅速轉(zhuǎn)換成目標(biāo)機(jī)器的匯編代碼。

使用場景

  • 對(duì)性能有很高要求的App/Module/游戲
  • 在Web中調(diào)用C/C++/Rust/Go的庫

開發(fā)工具

  • AssemblyScript 支持直接將TypeScript編譯成WebAssembly斑鸦,入門的門檻低支示。
  • Emscripten 可以說是WebAssembly的靈魂工具,上面說了很多編譯鄙才,這個(gè)就是那個(gè)編譯器颂鸿,將其他的高級(jí)語言,編譯成WebAssembly攒庵。
  • WABT 是個(gè)將WebAssembly在字節(jié)碼和文本格式相互轉(zhuǎn)換的一個(gè)工具嘴纺,方便開發(fā)者去理解wasm到底是在做什么事败晴。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市栽渴,隨后出現(xiàn)的幾起案子尖坤,更是在濱河造成了極大的恐慌,老刑警劉巖闲擦,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件慢味,死亡現(xiàn)場離奇詭異,居然都是意外死亡墅冷,警方通過查閱死者的電腦和手機(jī)纯路,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來寞忿,“玉大人驰唬,你說我怎么就攤上這事∏徽茫” “怎么了叫编?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長霹抛。 經(jīng)常有香客問我搓逾,道長,這世上最難降的妖魔是什么杯拐? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任恃逻,我火速辦了婚禮,結(jié)果婚禮上藕施,老公的妹妹穿的比我還像新娘寇损。我一直安慰自己,他們只是感情好裳食,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布矛市。 她就那樣靜靜地躺著,像睡著了一般诲祸。 火紅的嫁衣襯著肌膚如雪浊吏。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天救氯,我揣著相機(jī)與錄音找田,去河邊找鬼。 笑死着憨,一個(gè)胖子當(dāng)著我的面吹牛墩衙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼漆改,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼心铃!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起挫剑,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤去扣,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后樊破,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體愉棱,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年哲戚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了奔滑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡惫恼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出澳盐,到底是詐尸還是另有隱情祈纯,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布叼耙,位于F島的核電站腕窥,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏筛婉。R本人自食惡果不足惜簇爆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望爽撒。 院中可真熱鬧入蛆,春花似錦、人聲如沸硕勿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽源武。三九已至扼褪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間粱栖,已是汗流浹背话浇。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留闹究,地道東北人幔崖。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親岖瑰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子叛买,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • Javascript ,也叫Ecma script, 是這家伙用了 10 天時(shí)間趕出來的蹋订。率挣。 所以,各位程序猿們...
    自度君閱讀 2,160評(píng)論 1 7
  • (圖片來源:giphy.com) 編者按:本文由明非在眾成翻譯平臺(tái)上翻譯露戒。 最近椒功,WebAssembly 在 Ja...
    a6217200e10d閱讀 268,279評(píng)論 44 303
  • 1、WebAssembly是什么智什? WebAssembly 是一種低級(jí)的類匯編語言动漾,具有緊湊的二進(jìn)制格式,可以接近...
    前端小錢閱讀 2,175評(píng)論 0 0
  • 昨天晚上看到凌晨把一個(gè)人的朝圣看完了荠锭,這本書讓我感觸挺深的旱眯,一個(gè)身材高大的老人走過87天,600多英里证九,最終到達(dá)好...
    有點(diǎn)冷清的文藝范閱讀 238評(píng)論 0 1
  • 2018年7月18日中午一點(diǎn)到兩點(diǎn)半删豺,我家在挪空調(diào)。當(dāng)格力工作人員聯(lián)系我的時(shí)候愧怜,我很吃驚呀页,天外火辣辣的,簡...
    我為云朵閱讀 204評(píng)論 0 0