WebAssembly 系列(六)WebAssembly 的如今與將來

做者:Lin Clark

編譯:鬍子大哈 javascript

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

英文原文:Where is WebAssembly now and what’s next?html

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


本文是關於 WebAssembly 系列的第六篇文章(本系列共六篇文章),也同時是本系列的收尾文章。若是你沒有讀先前文章的話,建議先讀這裏。若是對 WebAssembly 沒概念,建議先讀這裏(中文文章)react

2017 年 2 月 28 日,四個主要的瀏覽器一致贊成宣佈 WebAssembly 的MVP 版本已經完成,它是一個瀏覽器能夠搭載的穩定版本。git

它提供了瀏覽器能夠搭載的穩定核,這個核並無包含 WebAssembly 組織所計劃的全部特徵,而是提供了可使 WebAssembly 穩定運行的基本版本。github

這樣一來開發者就可使用 WebAssembly 代碼了。對於舊版本的瀏覽器,開發者能夠經過 asm.js 來向下兼容代碼,asm.js 是 JavaScript 的一個子集,全部 JS 引擎均可以使用它。另外,經過 Emscripten 工具,你能夠把你的應用編譯成 WebAssembly 或者 asm.js。web

儘管是第一個版本,WebAssembly 已經能發揮出它的優點了,將來經過不斷地改善和融入新特徵,WebAssembly 會變的更快。瀏覽器

提高瀏覽器中 WebAssembly 的性能

隨着各類瀏覽器都使本身的引擎支持 WebAssembly,速度提高就變成天然而然的了,目前各大瀏覽器廠商都在積極推進這件事情。數據結構

JavaScript 和 WebAssembly 之間調用的中間函數

目前,在 JS 中調用 WebAssembly 的速度比本應達到的速度要慢。這是由於中間須要作一次「蹦牀運動」。JIT 沒有辦法直接處理 WebAssembly,因此 JIT 要先把 WebAssembly 函數發送到懂它的地方。這一過程是引擎中比較慢的地方。併發

按理來說,若是 JIT 知道如何直接處理 WebAssembly 函數,那麼速度會有百倍的提高。

若是你傳遞的是單一任務給 WebAssembly 模塊,那麼不用擔憂這個開銷,由於只有一次轉換,也會比較快。可是若是是頻繁地從 WebAssembly 和 JavaScript 之間切換,那麼這個開銷就必需要考慮了。

快速加載

JIT 必需要在快速加載和快速執行之間作權衡。若是在編譯和優化階段花了大量的時間,那麼執行的必然會很快,可是啓動會比較慢。目前有大量的工做正在研究,如何使預編譯時間和程序真正執行時間二者平衡。

WebAssembly 不須要對變量類型作優化假設,因此引擎也不關心在運行時的變量類型。這就給效率的提高提供了更多的可能性,好比可使編譯和執行這兩個過程並行。

加之最新增長的 JavaScript API 容許 WebAssembly 的流編譯,這就使得在字節流還在下載的時候就啓動編譯。

FireFox 目前正在開發兩個編譯器系統。一個編譯器先啓動,對代碼進行部分優化。在代碼已經開始運行時,第二個編譯器會在後臺對代碼進行全優化,當全優化過程完畢,就會將代碼替換成全優化版本繼續執行。

添加後續特性到 WebAssembly 標準的過程

WebAssembly 的發展是採用小步迭代的方式,邊測試邊開發,而不是預先設計好一切。

這就意味着有不少功能還在襁褓之中,沒有通過完全思考以及實際驗證。它們想要寫進標準,還要經過全部的瀏覽器廠商的積極參與。

這些特性叫作:將來特性。這裏列出幾個。

直接操做 DOM

目前 WebAssembly 沒有任何方法能夠與 DOM 直接交互。就是說你還不能經過好比 element.innerHTML 的方法來更新節點。

想要操做 DOM,必需要經過 JS。那麼你就要在 WebAssembly 中調用 JavaScript 函數(WebAssembly 模塊中,既能夠引入 WebAssembly 函數,也能夠引入 JavaScript 函數)。

無論怎麼樣,都要經過 JS 來實現,這比直接訪問 DOM 要慢得多,因此這是將來必定要解決的一個問題。

共享內存的併發性

提高代碼執行速度的一個方法是使代碼並行運行,不過有時也會拔苗助長,由於不一樣的線程在同步的時候可能會花費更多的時間。

這時若是可以使不一樣的線程共享內存,那就能下降這種開銷。實現這一功能 WebAssembly 將會使用 JavaScript 中的 SharedArrayBuffer,而這一功能的實現將會提升程序執行的效率。

SIMD(單指令,多數據)

若是你以前瞭解過 WebAssembly 相關的內容,你可能會據說過 SIMD,全稱是:Single Instruction, Multiple Data(單指令,多數據),這是並行化的另外一種方法。

SIMD 在處理存放大量數據的數據結構有其獨特的優點。好比存放了不少不一樣數據的 vector(容器),就能夠用同一個指令同時對容器的不一樣部分作處理。這種方法會大幅提升複雜計算的效率,好比遊戲或者 VR。

這對於普通 web 應用開發者不是很重要,可是對於多媒體、遊戲開發者很是關鍵。

異常處理

許多語言都仿照 C++ 式的異常處理,可是 WebAssembly 並無包含異常處理。

若是你用 Emscripten 編譯代碼,就知道它會模擬異常處理,可是這一過程很是之慢,慢到你都想用 「DISABLE_EXCEPTION_CATCHING」 標記把異常處理關掉。

若是異常處理加入到了 WebAssembly,那就不用採用模擬的方式了。而異常處理對於開發者來說又特別重要,因此這也是將來的一大功能點。

其餘改進——使開發者開發起來更簡單

一些將來特性不是針對性能的,而是使開發者開發 WebAssembly 更方便。

  • 一流的開發者工具。目前在瀏覽器中調試 WebAssembly 就像調試彙編同樣,不多的開發者能夠手動地把本身的源代碼和彙編代碼對應起來。咱們在致力於開發出更加適合開發者調試源代碼的工具。
  • 垃圾回收。若是你能提早肯定變量類型,那就能夠把你的代碼變成 WebAssembly,例如 TypeScript 代碼就能夠編譯成 WebAssembly。可是如今的問題是 WebAssembly 沒辦法處理垃圾回收的問題,WebAssembly 中的內存操做都是手動的。因此 WebAssembly 會考慮提供方便的 GC 功能,以方便開發者使用。
  • ES6 模塊集成。目前瀏覽器在逐漸支持用 script 標記來加載 JavaScript 模塊。一旦這一功能被完美執行,那麼像 <script src=url type="module"> 這樣的標記就能夠運行了,這裏的 url 能夠換成 WebAssembly 模塊。

總結

WebAssembly 執行起來更快,隨着瀏覽器逐步支持了 WebAssembly 的各類特性,WebAssembly 將會變得更快。


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

相關文章
相關標籤/搜索