[譯]WebAssembly: 帶有程式碼示例的簡單介紹

zoomdong發表於2020-02-16

WebAssembly: 帶有程式碼示例的簡單介紹

[譯]WebAssembly: 帶有程式碼示例的簡單介紹

為什麼要用 WebAssembly?

背景:Web 和 JavaScript

毫無疑問,web 具有高度移植性並且與機器無關,這使其能成為一個真正通用的平臺。

Web 是唯一真正的通用平臺。☝️

JavaScript(JS)是 Web 開發的預設語言。它有許多原生的 Web API 例如(DOM、Fetch、Web-sockets、Storage 等等),並且隨著瀏覽器功能越來越強大,我們正在使用 JavaScript(或者其它能轉譯成 JS 的語言)來編寫更復雜的客戶端程式。

但是在瀏覽器上執行一些大型的應用程式時,JavaScript 存在一些限制。

JavaScript 的限制

  • 不利於 CPU 密集型任務
  • JS 基於文字而非二進位制,因此需要下載更多的位元組,啟動時間也更長
  • JS 解釋和 JIT 優化會消耗 CPU 和電池壽命

JavaScript 執行管道

  • 需要用 JS 重寫已經存在的非 JS 庫、模組和應用程式

Web 開發社群正在嘗試克服這些限制,並通過引入 Web 開發新成員 WebAssembly 來向其它程式語言開放 Web。

在 2019 年 12 月 5 日,WebAssembly 和 HTMLCSSJavaScript 一樣,成為了第四個 Web 語言標準,能在瀏覽器上執行。

Web Assembly (WASM)

WebAssembly 是一種能在現代 Web 瀏覽器中執行的二進位制程式碼,它使得我們能用多種語言編寫程式碼並以接近本地執行的速度在 Web 上執行。

WASM 的功能

  • WASM 是一種不能由開發者編寫的底層語言,而是由其它語言例如 C/C++、Rust、AssemblyScript 編譯而來
  • WASM 是二進位制格式,因此只用下載更少的位元組(開發者也有等效的文字格式,稱為 WAT
  • 與 JS 不同,WASM 二進位制檔案無需任何優化就可以解碼和編譯成機器程式碼,因為在生成 WASM 二進位制檔案時就已經對其進行了優化

WebAssembly 執行管道

什麼時候使用 WebAssembly。

  • CPU 密集型任務,例如遊戲或其它圖形應用中的數學、影像和視訊處理等
  • 在 Web 上執行舊的 C/C++ 庫和應用程式,提供了可移植性,並且避免了將 C/C++ 程式碼用 JS 重寫的需求
  • 消除將原生應用程式和各種編譯目標作為單個 WASM 編譯的需求,可以使其通過 Web 瀏覽器在不同的處理器上執行

WASM 在這裡並不是要取代 JS,而是要與之一起工作。JavaScript 本身已經具有不錯的原生 Web API 集合,WASM 在這裡可以協助完成繁重的工作。

注意: 現代 JavaScript 引擎非常快速並且可以高度優化我們的 JS 程式碼,因此 WASM 軟體包的大小和執行時間對於簡單任務可能不是很有利。 在本文中,我不做任何基準測試,但請參考本文底部的參考資料,可以獲取基準測試連結。

怎麼使用 WASM(加深學習 ?)

生成和使用 WASM 概述

讓我們參照上述步驟在 C 中建立一個程式,用來計算數字的階乘並將其作為 WASM 在 JS 中使用。

C 編寫的計算階乘程式碼

我們可以使用 Emscripten 將上面 C 函式編譯成 WASM:

emcc factorial.c -s WASM=1 -o factorial.html
複製程式碼

它會生成 **factorial.wasm** 二進位制檔案以及 html-js 粘合程式碼。這裡引用了輸出目標的列表。

有效的可讀文字格式 WAT 如下所示。

factorial.wasm 的等效文字格式: **factorial.wat**

可以通過多種方式將 WASM 的二進位制資料傳送到 Web 客戶端,我們可以使用 javascript 的 **WebAssembly** API 編譯二進位制資料來建立 WASM 模組然後例項化這個模組來訪問匯出的功能。

載入 WASM 程式碼最有效、最優化的方法是使用 WebAssembly.instantiateStreaming() 這個直接從流式基礎源編譯和例項化 WebAssembly 模組的函式。

以下是使用 **instantiateStreaming** 來呼叫之前生成的 factorial.wasm 檔案的示例程式碼,該檔案可以由我們的伺服器提供,也可以被我們的 Web 客戶端按需呼叫。然後,我們可以使用以下 JS 程式碼例項化接收到的 WASM 模組,並可以訪問匯出的 factorial function

呼叫 WASM 檔案的 JS 程式碼

想快速理解所說明的步驟而無需進行繁瑣的設定,可以使用 WASM fiddle

瀏覽器支援

所有的現代瀏覽器(Chrome、Firefox、Safari、Edge)都支援 WebAssembly。點選此處以檢視最新的支援統計資訊

IE 不支援 WASM。如果需要在 IE 中使用 C/C++ 程式碼,我們可以使用 Emscripten 將其編譯為 asm.js(JS 的一個子集)。

未來

正在實現對執行緒管理垃圾收集的支援。這會讓 WebAssembly 更適合作為 JavaC#Go 之類的語言的編譯目標。

參考資料

如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章