WebAssembly 為什么比 asm.js 快?

作者:Alon Zakai

編譯:胡子大哈

翻譯原文:http://huziketang.com/blog/posts/detail?postId=58ce80d2a6d8a07e449fdd28

英文原文:Why WebAssembly is Faster Than asm.js

** 轉(zhuǎn)載請(qǐng)注明出處,保留原文鏈接以及作者信息**


本文作者:Alon Zakai

英文連接:Why WebAssembly is Faster Than asm.js

WebAssembly 是為 Web 而設(shè)計(jì)的、可以生成瀏覽器可執(zhí)行的二進(jìn)制文件的編程語(yǔ)言。并且于2017 年 2 月 28 日,四個(gè)主要的瀏覽器一致同意宣布 WebAssembly 的 MVP 版本已經(jīng)完成,即將推出一個(gè)瀏覽器可以搭載的穩(wěn)定版本。WebAssembly 的一個(gè)主要目標(biāo)就是變。本文將給出一些它如何變快的技術(shù)細(xì)節(jié)。

當(dāng)然,“快”是相對(duì)的概念。相比于 JavaScript 和其他動(dòng)態(tài)語(yǔ)言,WebAssembly 的快主要是因?yàn)樗?a target="_blank" rel="nofollow">靜態(tài)類(lèi)型特性和方便優(yōu)化特性。WebAssembly 意在速度上能夠達(dá)到和本地執(zhí)行一樣快,其實(shí) asm.js 已經(jīng)比較接近這一目標(biāo)了,但是 WebAssembly 要進(jìn)一步縮短和本地執(zhí)行速度之間的差距。因此本文著重介紹為什么 WebAssembly 比 asm.js 更快。

在開(kāi)始介紹之前,先做一些說(shuō)明:新的技術(shù)總是有一些還沒(méi)來(lái)得及優(yōu)化的情況,所以目前來(lái)說(shuō),并不是所有情況下 WebAssembly 都是最快的。本文主要表達(dá)的是 WebAssembly 為什么應(yīng)該是更快的。對(duì)于它還不是那么快的一些情況,也是未來(lái)需要 fix 的問(wèn)題。

那么有了這些標(biāo)準(zhǔn)以后,我們來(lái)介紹為什么 WebAssembly 更快。

1. 啟動(dòng)

WebAssembly 設(shè)計(jì)之初就定位在:體積更小、下載更快、解析更快,這樣即使應(yīng)用于一個(gè)大型的 web 應(yīng)用上啟動(dòng)也會(huì)很快。

JavaScript 代碼通過(guò) gzip 進(jìn)行壓縮,與本地代碼相比它已經(jīng)壓縮了很多,想要進(jìn)一步縮小它的體積確實(shí)不是一件容易的事情。但是通過(guò)對(duì) WebAssembly 文件大小的精心設(shè)計(jì)(LEB128 指標(biāo)),二進(jìn)制格式的 WebAssembly 的文件大小要比壓縮后的 JavaScript 文件更小。通常來(lái)講,要比 gzip 壓縮后的小 10% - 20%

WebAssembly 在解析過(guò)程有更大的進(jìn)步:它的解析速度要比 JavaScript 快一個(gè)數(shù)量級(jí)。這得益于 WebAssembly 的二進(jìn)制格式就是為更適合解析而設(shè)計(jì)的。同時(shí) WebAssembly 的解析和優(yōu)化函數(shù)也更容易實(shí)現(xiàn)并行,這一特點(diǎn)在多核機(jī)器上的體現(xiàn)更好。

影響啟動(dòng)時(shí)間的因素除了下載和解析以外還有很多,比如代碼的 VM 完全優(yōu)化、執(zhí)行之前下載所必須的額外文件等。但是下載和解析步驟是無(wú)論如何都不可避免的步驟,因此要盡可能地對(duì)它們進(jìn)行優(yōu)化。不論是對(duì)于瀏覽器還是 app,其他的影響因素都有辦法避免或者緩和它們的影響(例如代碼的完全優(yōu)化,可以通過(guò) WebAssembly 的基線編譯器或解釋器來(lái)避免)。

2. CPU 特性

使得 asm.js 這么快的技巧之一是利用好 CPU 特性。JavaScript 數(shù)字類(lèi)型都是 double 型的,在 asm.js 中加法操作后會(huì)有一個(gè)按位與的操作,這使得 double 加法這個(gè)操作,在邏輯上和 CPU 做簡(jiǎn)單的 int 加法(CPU 做簡(jiǎn)單 int 加操作很快)是等價(jià)的。而 asm.js 巧妙地通過(guò)這種方式使得 VM 可以更加有效地利用 CPU。

但是有一些 JavaScript 中表達(dá)的東西,asm.js 是表達(dá)不了的。
WebAssembly 則不受 JavaScript 的約束,我們一起來(lái)看一下更多的可利用的 CPU 特性:

  • 64 位整型。基于 64 位整型的操作速度可以快 4 倍。例如可以增加哈希算法和加密算法的速度。
  • 加載和存儲(chǔ)偏移量。它的用處特別廣泛,基本上所有包含域的內(nèi)存對(duì)象都涉及到偏移量的問(wèn)題(如 C 語(yǔ)言中 struct 等)。
  • 非對(duì)齊加載和存儲(chǔ)。這避免了 asm.js 所需要的 mask(asm.js 為 Typed Array 兼容而做的操作),同時(shí)這在幾乎所有的加載和存儲(chǔ)問(wèn)題都用得上。
  • 多種 CPU 指令,例如 popcount,copysign 等。每一個(gè)指令都有助于某種具體使用場(chǎng)景(例如,popcount 在密碼分析這個(gè)場(chǎng)景下很有用)。

在每一種具體場(chǎng)景下到底能起到多大作用,要依賴于如何使用上面提到的特性。和正常使用 asm.js 相比,我們的統(tǒng)計(jì)是大概比 asm.js 提升了 5% 的速率。未來(lái)還有更多可挖掘的 CPU 特性來(lái)提高速率,例如 SIMD

3. 工具鏈改進(jìn)

WebAssembly 是編譯器生成的主要目標(biāo),所以它的運(yùn)行主要包含兩個(gè)部分:生成它的編譯器(工具鏈端)和運(yùn)行它的虛擬機(jī)(瀏覽器端)。優(yōu)良的性能全都依賴于這兩部分。

對(duì)于 asm.js,情況也類(lèi)似,并且 Emscripten 做了一系列對(duì)工具鏈的優(yōu)化,還做了運(yùn)行 LLVM 的優(yōu)化器和 Emscripten 的 asm.js 優(yōu)化器。對(duì) WebAssembly 的優(yōu)化都是在這些的基礎(chǔ)上來(lái)設(shè)計(jì)的,并且同時(shí)還加入了一些專門(mén)針對(duì) WebAssembly 的改進(jìn)。我們自己在學(xué)習(xí) asm.js 的過(guò)程對(duì)我們改善 WebAssembly 很有幫助,尤其體現(xiàn)在一下幾個(gè)方面:

總的來(lái)說(shuō),這些工具鏈的改進(jìn),在 asm.js 的基礎(chǔ)上進(jìn)一步提升了 WebAssembly 的速度(Box2D 速度評(píng)測(cè)中,WebAssembly 的速度分別提升了 5% 和 7%)。

可預(yù)見(jiàn)的優(yōu)良性能

asm.js 的速度很接近本地執(zhí)行的速度了,但是它不可能在所有的瀏覽器中都達(dá)到同樣的標(biāo)準(zhǔn)。因?yàn)樵谑褂?asm.js 的過(guò)程中,一些人嘗試用一種方法來(lái)優(yōu)化 asm.js,而另一些人用另一種方法優(yōu)化,這導(dǎo)致了不同人有不同的版本和結(jié)果。雖然隨著時(shí)間的推移,大家對(duì)于 asm.js 也達(dá)成了某種共識(shí),但是對(duì)于 asm.js 來(lái)講,本質(zhì)問(wèn)題是它還是沒(méi)有一個(gè)統(tǒng)一的標(biāo)準(zhǔn)。它只是一個(gè)由一個(gè)廠商推出的,非標(biāo)準(zhǔn)的 JavaScript 子集而已,而它的使用者根據(jù)自己的偏好和習(xí)慣來(lái)使用它。

WebAssembly 則不同,它是由幾大主要的瀏覽器廠商共同設(shè)計(jì)的。與 JavaScript相比,JavaScript 只能通過(guò)一些創(chuàng)新方法或者 asm.js 這種方法來(lái)提高速度,而不論哪種方法都不可能適用于所有瀏覽器。WebAssembly 的優(yōu)化方案則得到了大多數(shù)廠商的認(rèn)可。對(duì)于 WebAssembly 來(lái)講,對(duì)于不同的 VM 依舊有很大的提升空間(如 AOT、JIT 有不同編譯方式)。不過(guò)能夠基本斷定的是,可以應(yīng)用于整個(gè)網(wǎng)絡(luò)的優(yōu)良性能是指日可期的。

想了解更多關(guān)于 WebAssembly 的知識(shí),請(qǐng)移步下面 WebAssembly 系列文章。

背景知識(shí):

當(dāng)前 WebAssembly 的狀況

WebAssembly 的未來(lái)

轉(zhuǎn)載請(qǐng)注明出處,保留原文鏈接以及作者信息

歡迎大家關(guān)注我的前端大哈 - 知乎專欄,定期發(fā)布高質(zhì)量前端文章。


我最近正在寫(xiě)一本《React.js 小書(shū)》,對(duì) React.js 感興趣的童鞋,歡迎指點(diǎn)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 官方中文版原文鏈接 感謝社區(qū)中各位的大力支持,譯者再次奉上一點(diǎn)點(diǎn)福利:阿里云產(chǎn)品券,享受所有官網(wǎng)優(yōu)惠,并抽取幸運(yùn)大...
    HetfieldJoe閱讀 2,357評(píng)論 1 21
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,552評(píng)論 25 708
  • 這座城市一開(kāi)始就不是我的選擇,只是因?yàn)闆](méi)能在成都留下來(lái),退而求其次罷了,如今已身在成都,還是決定寫(xiě)下回憶,紀(jì)念...
    珈琳諾閱讀 276評(píng)論 0 0
  • 回憶起從前的事,總讓人感到不安和無(wú)奈。很小的時(shí)候,我就是那種愛(ài)玩的孩子,直到高三。高三的壓力真是前所未有,那時(shí)的我...
    愿杯酒人生閱讀 1,244評(píng)論 0 1
  • 親愛(ài)的: 昨晚有一些人過(guò)來(lái)宿舍看貓呢。閑聊間,某個(gè)女孩子背了幾句古文,我頓時(shí)覺(jué)得她很有趣。 我真心懷念那個(gè)能背很多...
    余弦先生閱讀 459評(píng)論 0 2