WebAssembly 爲何比 asm.js 快?

做者:Alon Zakai

編譯:鬍子大哈 javascript

翻譯原文:huziketang.com/blog/posts/…

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

轉載請註明出處,保留原文連接以及做者信息html


本文做者:Alon Zakai前端

英文鏈接:Why WebAssembly is Faster Than asm.jsjava

WebAssembly 是爲 Web 而設計的、能夠生成瀏覽器可執行的二進制文件的編程語言。而且於2017 年 2 月 28 日,四個主要的瀏覽器一致贊成宣佈 WebAssembly 的 MVP 版本已經完成,即將推出一個瀏覽器能夠搭載的穩定版本。WebAssembly 的一個主要目標就是變。本文將給出一些它如何變快的技術細節。react

固然,「快」是相對的概念。相比於 JavaScript 和其餘動態語言,WebAssembly 的快主要是由於它的靜態類型特性和方便優化特性。WebAssembly 意在速度上可以達到和本地執行同樣快,其實 asm.js 已經比較接近這一目標了,可是 WebAssembly 要進一步縮短和本地執行速度之間的差距。所以本文着重介紹爲何 WebAssembly 比 asm.js 更快。git

在開始介紹以前,先作一些說明:新的技術老是有一些還沒來得及優化的狀況,因此目前來講,並非全部狀況下 WebAssembly 都是最快的。本文主要表達的是 WebAssembly 爲何應該是更快的。對於它還不是那麼快的一些狀況,也是將來須要 fix 的問題。github

那麼有了這些標準之後,咱們來介紹爲何 WebAssembly 更快。web

1. 啓動

WebAssembly 設計之初就定位在:體積更小、下載更快、解析更快,這樣即便應用於一個大型的 web 應用上啓動也會很快。算法

JavaScript 代碼經過 gzip 進行壓縮,與本地代碼相比它已經壓縮了不少,想要進一步縮小它的體積確實不是一件容易的事情。可是經過對 WebAssembly 文件大小的精心設計(LEB128 指標),二進制格式的 WebAssembly 的文件大小要比壓縮後的 JavaScript 文件更小。一般來說,要比 gzip 壓縮後的小 10% - 20%

WebAssembly 在解析過程有更大的進步:它的解析速度要比 JavaScript 快一個數量級。這得益於 WebAssembly 的二進制格式就是爲更適合解析而設計的。同時 WebAssembly 的解析和優化函數也更容易實現並行,這一特色在多核機器上的體現更好。

影響啓動時間的因素除了下載和解析之外還有不少,好比代碼的 VM 徹底優化、執行以前下載所必須的額外文件等。可是下載和解析步驟是不管如何都不可避免的步驟,所以要儘量地對它們進行優化。不管是對於瀏覽器仍是 app,其餘的影響因素都有辦法避免或者緩和它們的影響(例如代碼的徹底優化,能夠經過 WebAssembly 的基線編譯器或解釋器來避免)。

2. CPU 特性

使得 asm.js 這麼快的技巧之一是利用好 CPU 特性。JavaScript 數字類型都是 double 型的,在 asm.js 中加法操做後會有一個按位與的操做,這使得 double 加法這個操做,在邏輯上和 CPU 作簡單的 int 加法(CPU 作簡單 int 加操做很快)是等價的。而 asm.js 巧妙地經過這種方式使得 VM 能夠更加有效地利用 CPU。

可是有一些 JavaScript 中表達的東西,asm.js 是表達不了的。
WebAssembly 則不受 JavaScript 的約束,咱們一塊兒來看一下更多的可利用的 CPU 特性:

  • 64 位整型。基於 64 位整型的操做速度能夠快 4 倍。例如能夠增長哈希算法和加密算法的速度。
  • 加載和存儲偏移量。它的用處特別普遍,基本上全部包含域的內存對象都涉及到偏移量的問題(如 C 語言中 struct 等)。
  • 非對齊加載和存儲。這避免了 asm.js 所須要的 mask(asm.js 爲 Typed Array 兼容而作的操做),同時這在幾乎全部的加載和存儲問題都用得上。
  • 多種 CPU 指令,例如 popcount,copysign 等。每個指令都有助於某種具體使用場景(例如,popcount 在密碼分析這個場景下頗有用)。

在每一種具體場景下到底能起到多大做用,要依賴於如何使用上面提到的特性。和正常使用 asm.js 相比,咱們的統計是大概比 asm.js 提高了 5% 的速率。將來還有更多可挖掘的 CPU 特性來提升速率,例如 SIMD

3. 工具鏈改進

WebAssembly 是編譯器生成的主要目標,因此它的運行主要包含兩個部分:生成它的編譯器(工具鏈端)和運行它的虛擬機(瀏覽器端)。優良的性能全都依賴於這兩部分。

對於 asm.js,狀況也相似,而且 Emscripten 作了一系列對工具鏈的優化,還作了運行 LLVM 的優化器和 Emscripten 的 asm.js 優化器。對 WebAssembly 的優化都是在這些的基礎上來設計的,而且同時還加入了一些專門針對 WebAssembly 的改進。咱們本身在學習 asm.js 的過程對咱們改善 WebAssembly 頗有幫助,尤爲體如今一下幾個方面:

總的來講,這些工具鏈的改進,在 asm.js 的基礎上進一步提高了 WebAssembly 的速度(Box2D 速度評測中,WebAssembly 的速度分別提高了 5% 和 7%)。

可預見的優良性能

asm.js 的速度很接近本地執行的速度了,可是它不可能在全部的瀏覽器中都達到一樣的標準。由於在使用 asm.js 的過程當中,一些人嘗試用一種方法來優化 asm.js,而另外一些人用另外一種方法優化,這致使了不一樣人有不一樣的版本和結果。雖然隨着時間的推移,你們對於 asm.js 也達成了某種共識,可是對於 asm.js 來說,本質問題是它仍是沒有一個統一的標準。它只是一個由一個廠商推出的,非標準的 JavaScript 子集而已,而它的使用者根據本身的偏好和習慣來使用它。

WebAssembly 則不一樣,它是由幾大主要的瀏覽器廠商共同設計的。與 JavaScript相比,JavaScript 只能經過一些創新方法或者 asm.js 這種方法來提升速度,而不論哪一種方法都不可能適用於全部瀏覽器。WebAssembly 的優化方案則獲得了大多數廠商的承認。對於 WebAssembly 來說,對於不一樣的 VM 依舊有很大的提高空間(如 AOT、JIT 有不一樣編譯方式)。不過可以基本判定的是,能夠應用於整個網絡的優良性能是指日可期的。

想了解更多關於 WebAssembly 的知識,請移步下面 WebAssembly 系列文章。

背景知識:

當前 WebAssembly 的情況

WebAssembly 的將來

轉載請註明出處,保留原文連接以及做者信息

歡迎你們關注個人前端大哈 - 知乎專欄,按期發佈高質量前端文章。


我最近正在寫一本《React.js 小書》,對 React.js 感興趣的童鞋,歡迎指點

相關文章
相關標籤/搜索