圖說 WebAssembly(六):現狀與展望

本文是圖說 WebAssembly 系列文章的最後一篇。若是您還未閱讀以前的文章,建議您從第一篇入手。html

現狀

2017 年 2 月 28 日,主流的四大瀏覽器達成了共識並宣佈 WebAssembly 的最小可行產品(MVP)已經完成。這是 WebAssembly 搭載在瀏覽器上的第一個穩定初始版本。git

logo_party01-500x169.png

這也爲瀏覽器提供了一個穩定的 WebAssembly 核心。雖然該核心還很差漢社區組正在計劃的全部功能,但它也確實提供了足夠的功能,使得 WebAssembly 快速且可用。github

從這一刻開始,開發者也能夠開始發佈 WebAssembly 代碼了。對於較早版本的瀏覽器,開發者能夠回退到使用 asm.js 版本的代碼。由於 asm.js 是 JavaScript 的子集,因此任何 JavaScript 引擎均可以運行它。
若是使用 Emscripten 的話,還能夠把相同的應用編譯爲 WebAssembly 版本和 asm.js 版本的代碼。web

即便是最初的發行版本,WebAssembly 也是高性能的。可是隨着問題的修復和新功能的添加,它在將來將會擁有更高性能。segmentfault

提升性能

隨着瀏覽器逐步改進對 WebAssembly 的支持,性能提高也會慢慢的顯現。目前,瀏覽器廠商們正在獨自改進下面這些問題。瀏覽器

更快的函數調用

當前,在 JavaScript 中調用 WebAssembly 函數比想象的要慢。這是由於這個過程必須經歷一個稱爲彈跳(Trampolining)的過程。JIT 並不知道如何直接處理 WebAssembly,因此它必須把 WebAssembly 轉移到知道如何處理它的地方去。這在引擎內部是一個很慢的過程,該過程會創建用來運行 WebAssembly 代碼的準備過程。數據結構

06-02-trampoline01.png

這個種處理方式可能比直接由 JIT 處理慢 100 倍。併發

若是將一個大型任務交給 WebAssembly 模塊來完成的話,咱們可能不會注意到這種開銷。
可是若是咱們在 WebAssembly 和 JavaScript 之間來回屢次調用,那麼這個問題就凸顯出來了。dom

更快的加載

JIT 必須在更快的加載時間和更快的運行之間作出權衡。
若是花費更多的時間在編譯和優化,雖然能夠提高運行速度,可是也下降了啓動性能。函數

一個基本事實是,大多數的代碼的運行次數其實都還達不到須要優化的地步。
不過,目前有許多正在進行的研究,在尋找預編譯和這樣的基本事實之間的平衡點。

因爲 WebAssembly 並不須要推測數據類型,因此引擎也不須要在運行時監視這些數據類型的變化。
這也就給了咱們更多的選擇餘地,例如把編譯和運行並行化。

此外,最近新增的 JavaScript API 容許對 WebAssembly 進行流式編譯。也就是說,引擎能夠在 .wasm 還沒下載完成的時候就開始對已下載的內容進行編譯。

在 Firefox,咱們正在開發雙編譯系統。一個編譯器會提早運行,並把代碼優化工做作得至關不錯。等到運行代碼的時候,另外一個編譯器會在後臺進行全優化工做。一旦代碼優化完成,便會當即替換掉舊代碼。

新增功能

WebAssembly 的設計目標之一是先支持小部分功能並同步進行測試,而不是從一開始就把方方面面都設計好。

所以,它還有更多功能值得期待,不過新功能還沒進行周全的考慮。只有全部瀏覽器廠商都積極參與才能把新功能寫進規範。

如下是一些新功能。

直接操做 DOM

目前,WebAssembly 沒有任何方式可以操做 DOM 。因此咱們不能像使用 element.innerHTML 同樣,從 WebAssembly 裏更新一個 DOM 節點。

相反,必須經過 JavaScript 才能改變 DOM 節點。
也就是說,必須把新值返回給 JavaScript 調用方。或者在 WebAssembly 中調用 JavaScript 函數。這是能夠實現的,由於 JavaScript 和 WebAssembly 函數均可以作爲 WebAssembly 模塊的導入。

06-03-dom01-768x642.png

無論使用哪一種方式,繞道 JavaScript 確定比直接操做 DOM 要慢。這就致使了部分 WebAssembly 應用可能會所以而推遲發佈時間。

共享內存併發

有一種提升運行速度的辦法是,使不一樣代碼同時並行運行。
不過這有時候可能會偷雞不成蝕把米,由於線程間通訊可能比任務自己耗費的時間還多。

可是若是可以在不一樣線程之間共享內存,那麼這種狀況就會好不少。爲此,WebAssembly 可使用 JavaScript 的新接口 SharedArrayBuffer 來實現內存共享。一旦瀏覽器開始支持 SharedArrayBuffer,WebAssembly 工做小組就立馬能夠開始爲之制定相關標準。

SIMD

SIMD(Single Instruction, Multiple Data)是「單指令多數據」的縮寫。它是實現並行化的另外一種方式。

SIMD 能夠接受一個大型數據結構(好比一個包含不一樣數值的向量),而後對其中的不一樣數據同時應用相同的指令。這種方式能夠大幅提高遊戲或者 VR 中的各類複雜計算。

這對普通的網頁應用開發者可能沒那麼重要。可是對於像遊戲等多媒體應用開發者就顯得尤其重要了。

異常處理

不少語言都支持異常處理,可是 WebAssembly 還沒有有相關異常處理的規範。

若是你使用 Emscripten 編譯代碼,你會發現它會模擬某些編譯器優化級別的異常處理。
不過這會致使編譯變慢,可是你能夠經過 DISABLE_EXCEPTION_CATCHING 標誌來關閉它。

若是 WebAssembly 自己就可以處理異常,那麼這種異常模擬就不必了。

提高開發體驗的改進

也有一些將來的功能並不會影響性能,可是卻能提高 WebAssembly 的開發體驗。

  • 一等的源碼開發工具。目前,在瀏覽器中調試 WebAssembly 就像直接調試彙編。雖然仍是可以調試,可是基本上不多開發者可以把它跟源碼關聯起來。因此,咱們正在研究該如何改進工具支持,從而實現能夠直接調試源碼。
  • 垃圾回收。若是可以事先定義數據的類型,那麼就可以把這類代碼變成 WebAssembly 。因此使用 TypeScript 這類語言編寫的代碼,是能夠跟 WebAssembly 兼容的。不過,目前惟一的困難是 WebAssembly 還不知道該如何與現有的垃圾回收機制結合,就像 JavaScript 引擎內置的垃圾回收同樣。
  • ES6 模塊集成。瀏覽器目前正在完善使用 script 來加載模塊的功能。等到該功能完成後,把 <script src=url type="module"> 這種標籤指向 WebAssembly 模塊也應該是可以支持的。

結束

現現在 WebAssembly 已經至關快速。隨着新功能和改進逐步實現,相信它必定能夠變得更快!

相關文章
相關標籤/搜索