WebAssembly系列一:WebAssembly介紹

NO IMAGE

WebAssembly 介紹

出現 WebAssembly 的契機

JS 語言存在的缺陷

  1. JS只包含64位浮點數(double雙精度浮點數),遵循IEEE754標準,這會導致運算不準確的問題(如:0.1 + 0.2),當然現今的解決方案也很多,如:mathjsTC39 BigInt、將結果通過toPrecision + parseFloat處理等;
  2. JS的弱類型可能導致混亂與Bug,現今可以通過TS解決;
  3. JS不能像編譯語言一樣高效;
  4. 在之前,若要進行web開發必須使用JS,雖然業界有各式各樣的Transpiler,但歸根結底還是將其它源碼編譯成了JS,受限於JS的特性

谷歌與火狐對支持編譯語言的不同實現

谷歌Native Client(NaCl)(已廢棄)

NaCl使用SFI技術,使瀏覽器可以安全地運行原生代碼,並可以使用CPU的全部功能,PNaClNaCl增加了可移植性

PNaClNaCl的編譯與運行

WebAssembly系列一:WebAssembly介紹

PNaCl通過Pepper與瀏覽器JS之間通信

WebAssembly系列一:WebAssembly介紹

NaCl的廢棄

除Chrome以外,其它瀏覽器廠商認為使用NaCl(PNaCl),應用程序將運行在一個黑盒中,對其安全性產生質疑。最終2017年5月,NaCl被廢棄,取而代之的是WebAssembly

火狐asm.js

asm.js為開發人員提供了一種將c/c++源碼轉換為JS的方法(JS的嚴格子集)。例如使用Emscripten,c/c++代碼可以編譯為asm.js,js引擎識別到asm.js將會將其直接轉換為彙編,利用WebGL通過GPU執行asm.js,極大的提升運行速度。其次asm.js模塊也可以與JS模塊交互

JS的AOT編譯

WebAssembly系列一:WebAssembly介紹

asm.js是WebAssembly最小可行產品(MVP)的基礎

asm.js的缺點:asm.js是一個文本文件,在進行任何編譯前必須通過網絡傳輸,而Webassembly則採用二進制格式,其體積更小,因此傳輸效率更高

WebAssembly誕生

2015年4月,W3C成立WebAssembly工作組,用於監督與規範WebAssembly提案,倡導瀏覽器廠商使用一致性的規範。

WebAssembly的目標

  1. 規範瀏覽器廠商協作;
  2. JS使用WebAssembly代碼像導入一個模塊一樣簡單;
  3. 不取代JS引擎,僅僅是為其添加一個新特性。

WebAssembly實質

簡介

WebAssembly是一個底層虛擬機,.wasm 是基於堆棧虛擬機的二進制指令格式,WebAssembly的設計目標是編譯高級語言(c/c++/Rust等),提供可移植的結果,支持部署到web端及服務端

核心

  1. 核心規範
  2. JS API & Web API
  3. 二進制及文本格式(將文本格式代碼序列化為AST最終編譯為wasm二進制文件)

堆棧虛擬機

堆棧虛擬機由兩個元素組成:棧(數據結構)、指令,棧存在兩個操作:push、pop,遵循後進先出,棧還包括指向棧頂項的指針。指令表示要對棧裡面項執行的操作。

示例,下面ADD指令會彈出棧頂兩項,經過求和指令後,將結果推回棧:

WebAssembly系列一:WebAssembly介紹

WebAssembly編譯

WebAssembly的MVP專注於C/C++,所以編譯主要是通過Clang/LLVM/Emscripten等實現

WebAssembly語義階段

當瀏覽器獲取到.wasm文件(二進制),JS引擎將使用解碼棧解碼,將wasm文件轉換為AST,執行類型檢查,並將其解釋為執行函數。示例圖:

WebAssembly系列一:WebAssembly介紹

說明

階段說明
Decoding解碼,將二進制格式轉換為模塊
Validation驗證,對解碼後的模塊進行驗證(如類型檢查),以確保模塊良好且安全
Phase-1: Instantiation實例化第一階段,通過Globals、Memories、Tables,生成初始化模塊實例,並調用start()函數
Phase-2: Invocation實例化第二階段,導出函數:從模塊實例調用

應用場景

  • 圖像/視頻編輯
  • 遊戲
  • 音樂流媒體、緩存
  • 圖像識別
  • 直播視頻
  • VR & AR

雖然以上應用也可以使用JS,但使用WebAssembly可以極大的提升其性能,並且通過二進制文件可以極大的減少js編譯後文件(例如React的bundle)大小,在頁面上加載實例化wasm模塊可以加快代碼執行(WebAssembly自身線程)

限制

  • 暫時不支持GC,C/C++的內存管理構建在語言中,而JAVA使用GC(程序不再使用的對象佔用內存將被自動回收);
  • 不能直接訪問DOM,可以通過JS、Emscripten完成操作
  • 對老版本瀏覽器不兼容,當前支持Webassembly的瀏覽器

Emscripten

Emscripten是一個LLVM-to-JS的編譯器,其接受諸如Clang編譯產出的LLVM位碼輸出,並將其轉換為JS。Emscripten是一種構建、編譯、運行asm.js的技術組合。

生成wasm模塊,可以使用Emscripten SDK管理器:

WebAssembly系列一:WebAssembly介紹

其它

JS AST 示例

Webassembly 提案

相關文章

前端架構101(三):MVC啟示錄:模塊的職責,作用域和通信

前端架構101(二):MVC初探

微前端說明書

深入理解Webpack打包分塊(上)