幾張圖讓你看懂WebAssembly

(圖片來(lái)源:giphy.com)

編者按:本文由明非在眾成翻譯平臺(tái)上翻譯慢味。

最近,WebAssembly 在 JavaScript 圈非常的火!人們都在談?wù)撍嗝炊嗝纯欤鯓釉鯓痈淖?Web 開(kāi)發(fā)領(lǐng)域秃殉。但是沒(méi)有人講他到底為什么那么快坝初。在這篇文章里浸剩,我將會(huì)幫你了解 WebAssembly 到底為什么那么快。

第一鳄袍,我們需要知道它到底是什么绢要!WebAssembly 是一種可以使用非 JavaScript 編程語(yǔ)言編寫(xiě)代碼并且能在瀏覽器上運(yùn)行的技術(shù)方案。

當(dāng)大家談?wù)撈?WebAssembly 時(shí)拗小,首先想到的就是 JavaScript≈刈铮現(xiàn)在,我沒(méi)有必須在 WebAssembly 和 JavaScript 中選一個(gè)的意思哀九。實(shí)際上剿配,我們期待開(kāi)發(fā)者在一個(gè)項(xiàng)目中把 WebAssembly 和 JavaScript 結(jié)合使用。但是阅束,比較這兩者是有用的呼胚,這對(duì)你了解 WebAssembly 有一定幫助。

1. 一點(diǎn)點(diǎn)性能歷史

1995 年 JavaScript 誕生息裸。它的設(shè)計(jì)時(shí)間非常短蝇更,前十年發(fā)展迅速。

緊接著瀏覽器廠商們就開(kāi)始了更多的競(jìng)爭(zhēng)呼盆。

2008年年扩,人們稱(chēng)之為瀏覽器性能大戰(zhàn)的時(shí)期開(kāi)始了。很多瀏覽器加入了即時(shí)編譯器访圃,又稱(chēng)之為JITs厨幻。在這種模式下,JavaScript在運(yùn)行的時(shí)候腿时,JIT 選擇模式然后基于這些模式使代碼運(yùn)行更快况脆。

這些 JITs 的引入是瀏覽器運(yùn)行代碼機(jī)制的一個(gè)轉(zhuǎn)折點(diǎn)。所有的突然之間圈匆,JavaScript 的運(yùn)行速度快了10倍漠另。

隨著這種改進(jìn)的性能,JavaScript 開(kāi)始被用于意想不到的事情跃赚,比如使用Node.js和Electron構(gòu)建應(yīng)用程序笆搓。

現(xiàn)在 WebAssembly 可能是的另一個(gè)轉(zhuǎn)折點(diǎn)性湿。

在我們沒(méi)有搞清楚 JavaScript 和 WebAssembly 之間的性能差前,我們需要理解 JS 引擎所做的工作满败。

2. JavaScript 是如何在瀏覽器中運(yùn)行的呢肤频?

作為一個(gè)開(kāi)發(fā)人員,您將JavaScript添加到頁(yè)面時(shí)算墨,您有一個(gè)目標(biāo)并遇到一個(gè)問(wèn)題宵荒。

目標(biāo):你想要告訴計(jì)算機(jī)做什么

問(wèn)題:你和計(jì)算機(jī)使用不通的語(yǔ)言。

您說(shuō)的是人類(lèi)的語(yǔ)言净嘀,計(jì)算機(jī)說(shuō)的是機(jī)器語(yǔ)言报咳。盡管你不認(rèn)為 JavaScript 或者其他高級(jí)語(yǔ)言是人類(lèi)語(yǔ)言,但事實(shí)就是這樣的挖藏。它們的設(shè)計(jì)是為了讓人們認(rèn)知暑刃,不是為機(jī)器設(shè)計(jì)的。

所以JavaScript引擎的工作就是把你的人類(lèi)語(yǔ)言轉(zhuǎn)化成機(jī)器所理解的語(yǔ)言膜眠。

我想到電影《Arrival》岩臣,這就像人類(lèi)和外星人進(jìn)行交談。

在這部電影中宵膨,人類(lèi)語(yǔ)言不能從逐字翻譯成外星語(yǔ)言架谎。他們的語(yǔ)言反映出兩種對(duì)世界不同的認(rèn)知。人類(lèi)和機(jī)器也是這樣辟躏。

所以谷扣,怎么進(jìn)行翻譯呢?

在編程中鸿脓,通常有兩種翻譯方法將代碼翻譯成機(jī)器語(yǔ)言抑钟。你可以使用解釋器或者編譯器。

使用解釋器野哭,翻譯的過(guò)程基本上是一行一行及時(shí)生效的在塔。

編譯器是另外一種工作方式,它在執(zhí)行前翻譯拨黔。

每種翻譯方法都有利弊蛔溃。

2.1 解釋器的利弊

解釋器很快的獲取代碼并且執(zhí)行。您不需要在您可以執(zhí)行代碼的時(shí)候知道全部的編譯步驟篱蝇。因此贺待,解釋器感覺(jué)與 JavaScript 有著自然的契合。web 開(kāi)發(fā)者能夠立即得到反饋很重要零截。

這也是瀏覽器最開(kāi)始使用 JavaScript 解釋器的原因之一麸塞。

但是實(shí)用解釋器的弊端是當(dāng)你運(yùn)行相同的代碼的時(shí)候。比如涧衙,你執(zhí)行了一個(gè)循環(huán)哪工。然后你就會(huì)一遍又一遍的做同樣的事情奥此。

2.2 編譯器的利弊

編譯器則有相反的效果。在程序開(kāi)始的時(shí)候雁比,它可能需要稍微多一點(diǎn)的時(shí)間來(lái)了解整個(gè)編譯的步驟稚虎。但是當(dāng)運(yùn)行一個(gè)循環(huán)的時(shí)候他會(huì)更快,因?yàn)樗恍枰貜?fù)的去翻譯每一次循環(huán)里的代碼偎捎。

因?yàn)榻忉屍鞅仨氃诿看窝h(huán)訪問(wèn)時(shí)不斷重新轉(zhuǎn)換代碼蠢终,作為一個(gè)可以擺脫解釋器低效率的方法,瀏覽器開(kāi)始將編譯器引入茴她。

不同的瀏覽器實(shí)現(xiàn)起來(lái)稍有不同寻拂,但是基本目的是相同的。他們給 JavaScript 引擎添加了一個(gè)新的部分败京,稱(chēng)為監(jiān)視器(也稱(chēng)為分析器)兜喻。該監(jiān)視器在 JavaScript 運(yùn)行時(shí)監(jiān)控代碼梦染,并記錄代碼片段運(yùn)行的次數(shù)以及使用了那些數(shù)據(jù)類(lèi)型赡麦。

如果相同的代碼行運(yùn)行了幾次,這段代碼被標(biāo)記為 “warm”帕识。如果運(yùn)行次數(shù)比較多泛粹,就被標(biāo)記為 “hot”。

被標(biāo)記為 “warm” 的代碼被扔給基礎(chǔ)編譯器肮疗,只能提升一點(diǎn)點(diǎn)的速度晶姊。被標(biāo)記為 “hot” 的代碼被扔給優(yōu)化編譯器,速度提升的更多伪货。

了解更多们衙,可以讀?https://hacks.mozilla.org/2017/02/a-crash-course-in-just-in-time-jit-compilers/

3. 耗時(shí)比較:JavaScript Vs. WebAssembly

這張圖大致給出了現(xiàn)在一個(gè)程序的啟動(dòng)性能,目前 JIT 編譯器在瀏覽器中很常見(jiàn)碱呼。

該圖顯示了 JS 引擎運(yùn)行程序花費(fèi)的時(shí)間蒙挑。顯示的時(shí)間并不是平均的。這個(gè)圖片表明愚臀,JS 引擎做的這些任務(wù)花費(fèi)的時(shí)間取決于頁(yè)面中 JavaScript 做了什么事情忆蚀。但是我們可以用這個(gè)圖來(lái)構(gòu)建一個(gè)心理模型。

每欄顯示花費(fèi)在特定任務(wù)上的時(shí)間姑裂。

Parsing - 講源碼轉(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è)過(guò)程叫做重新優(yōu)化让网。

Execution - 執(zhí)行代碼的過(guò)程

Garbage collection - 清理內(nèi)存的時(shí)間

一個(gè)重要的事情要注意:這些任務(wù)不會(huì)發(fā)生在離散塊或特定的序列中。相反师痕,它們將被交叉執(zhí)行溃睹。比如正在做一些代碼解析時(shí),還執(zhí)行者一些其他的邏輯胰坟,有些代碼編譯完成后因篇,引擎又做了一些解析,然后又執(zhí)行了一些邏輯笔横,等等竞滓。

這種交叉執(zhí)行對(duì)早期 JavaScript 的性能有很大的幫助,早期的 JavaScript 的執(zhí)行就像下圖一樣:

一開(kāi)始吹缔,當(dāng)只有一個(gè)解釋器運(yùn)行 JavaScript 時(shí)商佑,執(zhí)行速度相當(dāng)緩慢。JITs 的引入厢塘,大大提升了執(zhí)行效率茶没。

監(jiān)視和編譯代碼的開(kāi)銷(xiāo)是需要權(quán)衡的事情。如果 JavaScript 開(kāi)發(fā)人員按照相同的方式編寫(xiě)JavaScript晚碾,解析和編譯時(shí)間將會(huì)很小抓半。但是,性能的提升使開(kāi)發(fā)人員能夠創(chuàng)建更大的JavaScript應(yīng)用程序格嘁。

這意味著還有改進(jìn)的余地笛求。

下面是 WebAssembly 如何比較典型 web 應(yīng)用。

瀏覽器的 JS 引擎有輕微的不同糕簿。我是基于 SpiderMonkey 來(lái)講探入。

3.1 請(qǐng)求

這沒(méi)有展示在圖上,但是從服務(wù)器獲取文件是會(huì)消耗時(shí)間的

下載執(zhí)行與 JavaScript 等效的 WebAssembly 文件需要更少的時(shí)間懂诗,因?yàn)樗捏w積更小蜂嗽。WebAssembly 設(shè)計(jì)的體積更小,可以以二進(jìn)制形式表示响禽。

即使使用 gzip 壓縮的 JavaScript文件很小徒爹,但 WebAssembly 中的等效代碼可能更小。

所以說(shuō)芋类,下載資源的時(shí)間會(huì)更少隆嗅。在網(wǎng)速慢的情況下更能顯示出效果來(lái)。

3.2 解析

JavaScript 源碼一旦被下載到瀏覽器侯繁,源將被解析為抽象語(yǔ)法樹(shù)(AST)胖喳。

通常瀏覽器解析源碼是懶惰的,瀏覽器首先會(huì)解析他們真正需要的東西贮竟,沒(méi)有及時(shí)被調(diào)用的函數(shù)只會(huì)被創(chuàng)建成存根丽焊。

在這個(gè)過(guò)程中较剃,AST被轉(zhuǎn)換為該 JS 引擎的中間表示(稱(chēng)為字節(jié)碼)。

相反技健,WebAssembly 不需要被轉(zhuǎn)換写穴,因?yàn)樗呀?jīng)是字節(jié)碼了。它僅僅需要被解碼并確定沒(méi)有任何錯(cuò)誤雌贱。

3.3 編譯 + 優(yōu)化

如前所述啊送,JavaScript 是在執(zhí)行代碼期間編譯的。因?yàn)?JavaScript 是動(dòng)態(tài)類(lèi)型語(yǔ)言欣孤,相同的代碼在多次執(zhí)行中都有可能都因?yàn)榇a里含有不同的類(lèi)型數(shù)據(jù)被重新編譯馋没。這樣會(huì)消耗時(shí)間。

相反降传,WebAssembly 與機(jī)器代碼更接近篷朵。例如,類(lèi)型是程序的一部分婆排。這是速度更快的一個(gè)原因:

編譯器不需要在運(yùn)行代碼時(shí)花費(fèi)時(shí)間去觀察代碼中的數(shù)據(jù)類(lèi)型声旺,在開(kāi)始編譯時(shí)做優(yōu)化。

編譯器不需要去每次執(zhí)行相同代碼中數(shù)據(jù)類(lèi)型是否一樣泽论。

更多的優(yōu)化在 LLVM 最前面就已經(jīng)完成了艾少。所以編譯和優(yōu)化的工作很少。

3.4 重新優(yōu)化

有時(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 中锁施,類(lèi)型是明確的陪踩,因此 JIT 不需要根據(jù)運(yùn)行時(shí)收集的數(shù)據(jù)對(duì)類(lèi)型進(jìn)行假設(shè)。這意味著它不必經(jīng)過(guò)重新優(yōu)化的周期悉抵。

3.5 執(zhí)行

盡可能編寫(xiě)執(zhí)行性能好的 JavaScript肩狂。所以,你可能需要知道 JIT 是如何做優(yōu)化的姥饰。

然而傻谁,大多數(shù)開(kāi)發(fā)者并不知道 JIT 的內(nèi)部原理。即使是那些了解 JIT 內(nèi)部原理的開(kāi)發(fā)人員列粪,也很難實(shí)現(xiàn)最佳的方案审磁。有很多時(shí)候谈飒,人們?yōu)榱耸顾麄兊拇a更易于閱讀(例如:將常見(jiàn)任務(wù)抽象為跨類(lèi)型工作的函數(shù))會(huì)阻礙編譯器優(yōu)化代碼。

正因如此态蒂,執(zhí)行 WebAssembly 代碼通常更快杭措。有些必須對(duì) JavaScript 做的優(yōu)化不需要用在 WebAssembly 上

另外,WebAssembly 是為編譯器設(shè)計(jì)的钾恢。意思是瓤介,它是專(zhuān)門(mén)給編譯器來(lái)閱讀,并不是當(dāng)做編程語(yǔ)言讓程序員去寫(xiě)的赘那。

由于程序員不需要直接編程刑桑,WebAssembly 提供了一組更適合機(jī)器的指令。根據(jù)您的代碼所做的工作募舟,這些指令的運(yùn)行速度可以在10%到800%之間祠斧。

3.6 垃圾回收

在 JavaScript 中,開(kāi)發(fā)者不需要擔(dān)心內(nèi)存中無(wú)用變量的回收拱礁。JS 引擎使用一個(gè)叫垃圾回收器的東西來(lái)自動(dòng)進(jìn)行垃圾回收處理琢锋。

這對(duì)于控制性能可能并不是一件好事。你并不能控制垃圾回收時(shí)機(jī),所以它可能在非常重要的時(shí)間去工作,從而影響性能出吹。

現(xiàn)在幢踏,WebAssembly 根本不支持垃圾回收。內(nèi)存是手動(dòng)管理的(就像 C/C++)六荒。雖然這些可能讓開(kāi)發(fā)者編程更困難,但它的確提升了性能。

總而言之鸟悴,這些都是在許多情況下,在執(zhí)行相同任務(wù)時(shí)WebAssembly 將勝過(guò) JavaScript 的原因奖年。

在某些情況下细诸,WebAssembly 不能像預(yù)期的那樣執(zhí)行,還有一些更改使其更快陋守。我在另一篇文章中更深入地介紹了這些未來(lái)的功能震贵。

4. WebAssembly 是如何工作的?

現(xiàn)在水评,您了解開(kāi)發(fā)人員為什么對(duì) WebAssembly 感到興奮猩系,讓我們來(lái)看看它是如何工作的。

當(dāng)我談到上面的 JIT 時(shí)之碗,我談到了與機(jī)器的溝通像與外星人溝通蝙眶。

我現(xiàn)在想看看這個(gè)外星人的大腦如何工作 - 機(jī)器的大腦如何解析和理解交流內(nèi)容。

這個(gè)大腦的一部分是專(zhuān)注于思考,例如算術(shù)和邏輯幽纷。有一部分腦部提供短期記憶式塌,另一部分提供長(zhǎng)期記憶。

這些不同的部分都有名字友浸。

負(fù)責(zé)思考的部分是算術(shù)邏輯單元(ALU)峰尝。

短期儲(chǔ)存由寄存器(Registers)提供。

隨機(jī)存儲(chǔ)器(或RAM)來(lái)提供長(zhǎng)期儲(chǔ)存能力收恢。

機(jī)器碼中的語(yǔ)句被稱(chēng)為指令武学。

當(dāng)一條指令進(jìn)入大腦時(shí)會(huì)發(fā)生什么?它被拆分成了多個(gè)的部分并有特殊的含義伦意。

被拆分成的多個(gè)部分分別進(jìn)入不同的大腦單元進(jìn)行處理火窒,這也是拆分指令所依賴(lài)的方式。

例如驮肉,這個(gè)大腦從機(jī)器碼中取出4-10位熏矿,并將它們發(fā)送到 ALU。ALU進(jìn)行計(jì)算离钝,它根據(jù) 0 和 1 的位置來(lái)確定是否需要將兩個(gè)數(shù)相加票编。

這個(gè)塊被稱(chēng)為“操作碼”,因?yàn)樗嬖V ALU 執(zhí)行什么操作卵渴。

那么這個(gè)大腦會(huì)拿后面的兩個(gè)塊來(lái)確定他們所要操作的數(shù)慧域。這兩個(gè)塊對(duì)應(yīng)的是寄存器的地址。

請(qǐng)注意添加在機(jī)器碼上面的標(biāo)注(ADD R1 R2)浪读,這使我們更容易了解發(fā)生了什么昔榴。這就是匯編。它被稱(chēng)為符號(hào)機(jī)器碼瑟啃。這樣人類(lèi)也能看懂機(jī)器碼的含義论泛。

您可以看到,這個(gè)機(jī)器的匯編和機(jī)器碼之間有非常直接的關(guān)系蛹屿。每種機(jī)器內(nèi)部有不同的結(jié)構(gòu),所以每種機(jī)器都有自己獨(dú)有的匯編語(yǔ)言岩榆。

所以我們并不只有一個(gè)翻譯的目標(biāo)错负。

相反,我們的目標(biāo)是不同類(lèi)型的機(jī)器碼勇边。就像人類(lèi)說(shuō)不同的語(yǔ)言一樣犹撒,機(jī)器也有不同的語(yǔ)言。

您希望能夠?qū)⑦@些任何一種高級(jí)編程語(yǔ)言轉(zhuǎn)換為任何一種匯編語(yǔ)言粒褒。這樣做的一個(gè)方法是創(chuàng)建一大堆不同的翻譯器识颊,可以從任意一種語(yǔ)言轉(zhuǎn)換成任意一種匯編語(yǔ)言。

這樣做的效率非常低。為了解決這個(gè)問(wèn)題祥款,大多數(shù)編譯器會(huì)在高級(jí)語(yǔ)言和匯編語(yǔ)言之間多加一層清笨。編譯器將把高級(jí)語(yǔ)言翻譯成一種更低級(jí)的語(yǔ)言,但比機(jī)器碼的等級(jí)高刃跛。這就是中間代碼(IR)抠艾。

意思就是編譯器可以將任何一種高級(jí)語(yǔ)言轉(zhuǎn)換成一種中間語(yǔ)言。然后桨昙,編譯器的另外的部分將中間語(yǔ)言編譯成目標(biāo)機(jī)器的匯編代碼检号。

編譯器的“前端”將高級(jí)編程語(yǔ)言轉(zhuǎn)換為IR。編譯器的“后端”將 IR 轉(zhuǎn)換成目標(biāo)機(jī)器的匯編代碼蛙酪。

4.1 WebAssembly 適合在哪里使用齐苛?

您可能會(huì)將 WebAssembly 當(dāng)做是另外一種目標(biāo)匯編語(yǔ)言。這是真的桂塞,這些機(jī)器語(yǔ)言(x86凹蜂,ARM等)中的每一種都對(duì)應(yīng)于特定的機(jī)器架構(gòu)。

當(dāng)你的代碼運(yùn)行在用戶(hù)的機(jī)器的 web 平臺(tái)上的時(shí)候藐俺,你不知道你的代碼將會(huì)運(yùn)行在那種機(jī)器結(jié)構(gòu)上炊甲。

所以 WebAssembly 和別的匯編語(yǔ)言是有一些不同的。所以他是一個(gè)概念機(jī)上的機(jī)器語(yǔ)言欲芹,不是在一個(gè)真正存在的物理機(jī)上運(yùn)行的機(jī)器語(yǔ)言卿啡。

正因如此,WebAssembly 指令有時(shí)候被稱(chēng)為虛擬指令菱父。它比 JavaScript 代碼更快更直接的轉(zhuǎn)換成機(jī)器代碼颈娜,但它們不直接和特定硬件的特定機(jī)器代碼對(duì)應(yīng)。

在瀏覽器下載 WebAssembly后浙宜,使 WebAssembly 的迅速轉(zhuǎn)換成目標(biāo)機(jī)器的匯編代碼官辽。

如果想在您的頁(yè)面里上添加 WebAssembly,您需要將您的代碼編譯成 .wasm 文件粟瞬。

5. 編譯到 .wasm 文件

當(dāng)前對(duì) WebAssembly 支持最多的編譯器工具鏈稱(chēng)是 LLVM同仆。有許多不同的“前端”和“后端”可以插入到 LLVM 中。

注意:大多數(shù) WebAssembly 模塊開(kāi)發(fā)者使用 C 和 Rust 編寫(xiě)代碼裙品,然后編譯成 WebAssembly俗批,但是這里有其他創(chuàng)建 WebAssembly 模塊的途徑。比如市怎,這里有一個(gè)實(shí)驗(yàn)性工具岁忘,他可以幫你使用 Type 創(chuàng)建一個(gè) WebAssembly 模塊,你可以在這里直接編輯WebAssembly区匠。

架設(shè)我們想通過(guò) C 來(lái)創(chuàng)建 WebAssembly干像。我們可以使用 clang “前端” 從 C 編譯成 LLVM 中間代碼。當(dāng)它變成 LLVM 的中間代碼(IR)以后,LLVM 可以理解他麻汰,所以 LLVM 可以對(duì)代碼做一些優(yōu)化速客。

如果想讓 LLVM 的 IR 變成 WebAssembly,我們需要一個(gè) “后端”什乙。目前 LLVM 項(xiàng)目中有一個(gè)正在開(kāi)發(fā)中的挽封。這個(gè)“后端”對(duì)做這件事情很重要,應(yīng)該很快就會(huì)完成臣镣「ㄔ福可惜,它現(xiàn)在還不能用忆某。

另外有一個(gè)工具叫做 Emen点待,它用起來(lái)比較簡(jiǎn)單。它還可以有比較有用的可以選擇弃舒,比如說(shuō)由 IndexDB 支持的文件系統(tǒng)癞埠。

不管你使用的什么工具鏈,最終的結(jié)果都應(yīng)該是以 .wasm 結(jié)尾的文件聋呢。來(lái)讓我們看一下如何將它用在你的 web 頁(yè)面苗踪。

6. 在 JavaScript 中加載一個(gè) .wasm 組件

.wasm 文件是 WebAssembly 組件,它可以被 JavaScript 加載削锰。到目前為止通铲,加載過(guò)程有點(diǎn)復(fù)雜。

functionfetchAndInstantiate(url,importObject){

returnfetch(url).then(response?=>

response.arrayBuffer()

).then(bytes?=>

WebAssembly.instantiate(bytes,importObject)

).then(results?=>

results.instance

);

}

您可以在文檔中更深入地了解這些器贩。

我們正在努力使這個(gè)過(guò)程更容易颅夺。我們期望對(duì)工具鏈進(jìn)行改進(jìn),并與現(xiàn)有的模塊管理工具(如Webpack)或加載器(如SystemJS)相結(jié)合蛹稍。我相信吧黄,加載 WebAssembly 模塊越來(lái)越簡(jiǎn)單,就像加載 JavaScript 一樣唆姐。

但是拗慨,WebAssembly模塊和JS模塊之間存在重大差異。目前奉芦,WebAssembly 中的函數(shù)只能使用 WebAssembly 類(lèi)型(整數(shù)或浮點(diǎn)數(shù))作為參數(shù)或返回值胆描。

對(duì)于任何更復(fù)雜的數(shù)據(jù)類(lèi)型(如字符串),必須使用 WebAssembly 模塊的內(nèi)存仗阅。

如果你之前主要使用 JavaScript,可能對(duì)于直接訪問(wèn)內(nèi)存是不熟悉的国夜。C减噪,C ++和Rust等性能更高的語(yǔ)言往往具有手動(dòng)內(nèi)存管理功能。WebAssembly 模塊的內(nèi)存模擬這些語(yǔ)言中的堆。

為此筹裕,它使用 JavaScript 中稱(chēng)為 ArrayBuffer醋闭。ArrayBuffer 是一個(gè)字節(jié)數(shù)組。因此朝卒,數(shù)組的索引作為內(nèi)存地址证逻。

如果要在 JavaScript 和 WebAssembly 之間傳遞一個(gè)字符串,需要將字符轉(zhuǎn)換為等效的字符碼抗斤。然后你需要將它寫(xiě)入內(nèi)存數(shù)組囚企。由于索引是整數(shù),所以可以將索引傳遞給 WebAssembly 函數(shù)瑞眼。因此龙宏,字符串的第一個(gè)字符的索引可以當(dāng)作指針。

任何人開(kāi)發(fā)的 WebAssembly 模塊很可能被 Web 開(kāi)發(fā)人員使用并為該模塊創(chuàng)建一個(gè)的裝飾器伤疙。這樣银酗,您當(dāng)做用戶(hù)來(lái)使用這個(gè)模塊就不需要考慮內(nèi)存管理的事情了。

我已經(jīng)在另一篇文章中解釋了更多關(guān)于使用WebAssembly模塊的內(nèi)容徒像。

7. WebAssembly 現(xiàn)在是什么狀態(tài)黍特?

二月二十八日,四大瀏覽器宣布達(dá)成共識(shí)锯蛀,即 WebAssembly 的 MVP (最小化可行產(chǎn)品)已經(jīng)完成灭衷。大約一周后,F(xiàn)irefox會(huì)默認(rèn)打開(kāi) WebAssembly 支持谬墙,而Chrome則在第二周開(kāi)始今布。它也可用于預(yù)覽版本的Edge和Safari。

這提供了一個(gè)穩(wěn)定的初始版本拭抬,瀏覽器開(kāi)始支持部默。

該核心不包含社區(qū)組織計(jì)劃的所有功能。即使在初始版本中造虎,WebAssembly 也會(huì)很快傅蹂。但是,通過(guò)修復(fù)和新功能的組合算凿,將來(lái)應(yīng)該能夠更快份蝴。我在另一篇文章中詳細(xì)介紹了這些功能。

8. 總結(jié)

使用WebAssembly氓轰,可以更快地在 web 應(yīng)用上運(yùn)行代碼婚夫。這里有 幾個(gè) WebAssembly 代碼運(yùn)行速度比 JavaScript 高效的原因。

文件加載 - WebAssembly 文件體積更小署鸡,所以下載速度更快案糙。

解析 - 解碼 WebAssembly 比解析 JavaScript 要快

編譯和優(yōu)化 - 編譯和優(yōu)化所需的時(shí)間較少限嫌,因?yàn)樵趯⑽募扑偷椒?wù)器之前已經(jīng)進(jìn)行了更多優(yōu)化,JavaScript 需要為動(dòng)態(tài)類(lèi)型多次編譯代碼

重新優(yōu)化 - WebAssembly 代碼不需要重新優(yōu)化时捌,因?yàn)榫幾g器有足夠的信息可以在第一次運(yùn)行時(shí)獲得正確的代碼

執(zhí)行 - 執(zhí)行可以更快怒医,WebAssembly 指令更接近機(jī)器碼

垃圾回收 - 目前 WebAssembly 不直接支持垃圾回收,垃圾回收都是手動(dòng)控制的奢讨,所以比自動(dòng)垃圾回收效率更高稚叹。

目前瀏覽器中的 MVP(最小化可行產(chǎn)品) 已經(jīng)很快了。在接下來(lái)的幾年里拿诸,隨著瀏覽器的發(fā)展和新功能的增加扒袖,它將在未來(lái)幾年內(nèi)變得更快。沒(méi)有人可以肯定地說(shuō)佳镜,這些性能改進(jìn)可以實(shí)現(xiàn)什么樣的應(yīng)用僚稿。但是,如果過(guò)去有任何跡象蟀伸,我們可以期待驚奇蚀同。

本文鏈接:http://www.reibang.com/p/bff8aa23fe4d

這是英文原文?https://www.smashingmagazine.com/2017/05/abridged-cartoon-introduction-webassembly/?

這是中文原文?https://www.zcfy.cc/article/an-abridged-cartoon-introduction-to-webassembly-ndash-smashing-magazine

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市啊掏,隨后出現(xiàn)的幾起案子蠢络,更是在濱河造成了極大的恐慌,老刑警劉巖迟蜜,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刹孔,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡娜睛,警方通過(guò)查閱死者的電腦和手機(jī)髓霞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)畦戒,“玉大人方库,你說(shuō)我怎么就攤上這事≌险” “怎么了纵潦?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)垃环。 經(jīng)常有香客問(wèn)我邀层,道長(zhǎng),這世上最難降的妖魔是什么遂庄? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任寥院,我火速辦了婚禮,結(jié)果婚禮上涛目,老公的妹妹穿的比我還像新娘只磷。我一直安慰自己经磅,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布钮追。 她就那樣靜靜地躺著,像睡著了一般阿迈。 火紅的嫁衣襯著肌膚如雪元媚。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天苗沧,我揣著相機(jī)與錄音刊棕,去河邊找鬼。 笑死待逞,一個(gè)胖子當(dāng)著我的面吹牛甥角,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播识樱,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼嗤无,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了怜庸?” 一聲冷哼從身側(cè)響起当犯,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎割疾,沒(méi)想到半個(gè)月后嚎卫,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宏榕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年拓诸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片麻昼。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡奠支,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出涌献,到底是詐尸還是另有隱情胚宦,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布燕垃,位于F島的核電站枢劝,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏卜壕。R本人自食惡果不足惜您旁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望轴捎。 院中可真熱鬧鹤盒,春花似錦蚕脏、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至尺碰,卻和暖如春挣棕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背亲桥。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工洛心, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人题篷。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓词身,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親番枚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子法严,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

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