WebAssembly:未來的字節編碼技術
本文作者是 360 奇舞團的前端工程師
本文爲翻譯,原文略做修改以符合中文語境 原文標題:WebAssembly: byte-code of the future 原文作者:Joshua Nussbaum 原文地址:https://dev.to/joshnuss/webassembly-byte-code-of-the-future-402p
自從 Netscape 推出 JavaScript 以來,一直有一些開發者喜歡它,而另一些則不喜歡。
如果瀏覽器支持更多的編程語言那就太好了,不管你站在哪一邊,我想我們都一致同意。
這是 WebAssembly 的承諾:提供任何編程語言都可以編譯的通用運行時。
過去的嘗試
在網絡的早期,人們嘗試使用 Java Applet 和 Microsoft ActiveX 進行擴展;但兩者都受到安全問題的困擾,最終被放棄;問題是它們在沒有訪問控制的情況下執行,這成爲了一個巨大的挑戰。
後來 Macromedia Flash 和 Silverlight 取得了一些成功,但最終也遭遇了同樣的悲慘命運;它們都缺乏開放標準,這使得瀏覽器和操作系統供應商很難支持。
什麼是 WebAssembly?
WebAssembly(又名 WASM)是一種 開放標準 [1] 字節代碼格式,適用於所有瀏覽器。它是一種低級二進制格式和執行引擎,概念上類似於 Oracle 的 JVM 或 Microsoft 的 CLR。
它的設計初衷就是爲了託管和安全,它無法訪問機器的內存或硬盤。只有主機可以決定公開哪些 API。
WASM 是一種可移植格式,因此可以支持多種編程語言,認爲 Rust、Ruby、Python 甚至 JavaScript 都可以編譯爲 WASM 字節代碼。
儘管它最初是針對瀏覽器而設計的,但它在瀏覽器之外也能很好地工作。
它可以在服務器上、雲端、硬件設備上運行,或者使用插件系統。
編寫 WASM
創建.wasm
文件有多種方式:
-
手動編寫(不建議,因爲 WebAssembly 的字節碼是一種低級別的二進制表示形式,編寫起來非常複雜和容易出錯)
-
使用 Wasm 文本格式 [2] 編寫。
-
使用更高級的語言,如 AssemblyScript、Rust、Ruby 等,然後編譯它。
我們通過以下幾個例子來看下:
什麼是 WAT
WAT(Wasm Text Format)是 WebAssembly 規範提供的一種用於定義 WebAssembly 模塊的文本格式;它使用 S 表達式(S-expressions)的語法,類似於 Lisp 或 Clojure。
例如,以下是一個簡單的 WAT 示例,表示一個將兩個數字相加的 WebAssembly 函數:
; define a module
(module
; define a function called "add"
; it takes 2 params:
; - $a is a 32-bit integer
; - $b is a 32-bit integer
; it returns an 32-bit integer
(fun add (param $a i32) (param $b i32) (result $i32)
; load param $a onto the stack
local.get $a
; load param $b onto the stack
local.get $b
; perform 32-bit integer "add" operation
i32.add
; the last value on the stack is returned
; which is the result of the `i32.add`
)
)
使用 wat2wasm WebAssembly Toolkit CLI 工具 [3] 編譯. wat 文件
# outputs example.wasm
> wat2wasm example.wat
編譯產出 example.wasm 可以在任何主機執行,使用 wasmtime
命令行工具來執行
# invoke "add" function, and pass args 1,2
> wasmtime example.wasm --invoke add 1 2
3
AssemblyScript
還有一種稱爲 AssemblyScript[4] 的高級語言;它就像是 WebAssembly 的 TypeScript。
如果我們用 AssemblyScript 重寫上面例子中的add()
函數,它將如下所示:
// in add.ts
export function add(a: u32, b: u32): u32 {
return a + b;
}
這樣對比來看,更具有可讀性,對前端開發來講更友好;
然後使用 AssemblyScript 的編譯器asc
來編譯:
pnpm install -D assemblyscript
pnpm run asc add.ts --outFile=math.wasm
格式對比
爲了比較 AssemblyScript 和 WAT 格式,我創建了一個小工具:
https://assemblyscript-play.vercel.app
您還可以使用 CLI 工具 wasm2wat
來比較這兩種格式:
# outputs .wat format
wasm2wat math.wasm
運行時執行
就像編譯 wasm 的方式有很多種一樣,執行它的方法也有很多種。
在瀏覽器中使用 WebAssembly
要在瀏覽器中使用 WebAssembly API,首先加載 WebAssembly 模塊:
// fetch .wasm file
const response = fetch('/path/to/some.wasm')
// instantiate module with streaming
const module = WebAssembly.instantiateStreaming(response)
然後,調用導出的add
的函數:
const result = module.instance.exports.add(1, 2)
還可以向模塊傳遞其他方法,例如可以共享 console.log
方法:
// fetch .wasm file
const response = fetch('/path/to/some.wasm')
// instantiate module and pass an api
const module = WebAssembly.instantiateStreaming(response, {
imports: {
// share console.log
log: console.log
}
})
在服務器上使用 WebAssembly
WebAssembly 也可以在服務器上執行,使用的方法與在瀏覽器中的幾乎相同。
唯一不同的是,不使用 URL 從服務器獲取. wasm 文件,而是使用 fs.readFile()
從磁盤上讀取它:
import fs from 'fs'
// read .wasm file
const bytes = await fs.promises.readFile('/path/to/some.wasm')
// instantiate the module
const module = WebAssembly.instantiate(bytes)
然後,調用 add
函數:
const result = module.instance.exports.add(1, 2)
還可以從許多其他編程語言中執行此操作,例如 rust[5]、ruby[6]、 python[7] 或來自 CLI[8] 。
在雲端使用 WebAssembly
WebAssembly 在雲端也有一些重要的應用場景。
與 JavaScript 雲函數相比,它具備一些明顯的優勢:
-
無冷啓動:主機只需加載一個. wasm 文件,而不是整個應用程序;典型的 JavaScript 應用包含許多需要加載的文件,這會耗費較長的時間。
-
更快的部署:需要上傳的僅僅是一個簡單的二進制文件。
-
多語言託管:所有可以編譯爲 WebAssembly 的編程語言都可以在雲中部署,無需特殊的運行時環境。
-
快照:執行狀態可以進行快照;例如,一個在初始化期間執行大量計算的應用程序可以創建快照。隨後的請求可以從快照狀態開始,從而避免浪費大量的啓動時間。
注意事項
關於 WebAssembly,仍然存在一些問題:
-
WebAssembly 仍然相對較新,並且正在積極開發中,儘管它正在不停的迭代中,但仍存在一些尚未完善的方面。
-
尚未爲某些編程語言提供完整的支持。
-
WebAssembly 沒有像字符串或標準庫等基本數據類型,這是故意設計的,各編程語言需要自行提供其標準庫。
-
由於 “標準庫” 需要包含在. wasm 文件中,這可能會導致文件變得較大。
我相信,這些大多數問題會隨着時間的推移將得到解決。
未來前景
在過去幾年中,WebAssembly 取得了許多進展。
最終,幾乎所有編程語言都將具備編譯到 WebAssembly 的能力,並提供適用於託管 WebAssembly 的運行時環境(如果尚未提供的話);這將使所有編程語言都能夠在瀏覽器、服務器甚至硬件上運行。
這也可能催生出專爲適應 WebAssembly 主導的編程環境而設計的新型編程語言。
參考資料
[1] 開放標準 https://www.w3.org/groups/wg/wasm[2] Wasm 文本格式 https://webassembly.github.io/spec/core/text/index.html[3] WebAssembly Toolkit CLI 工具 https://github.com/WebAssembly/wabt[4] AssemblyScript https://www.assemblyscript.org/[5] rust https://docs.rs/wasmer/latest/wasmer[8] ruby https://github.com/wasmerio/wasmer-ruby[7] python https://github.com/wasmerio/wasmer-python[8] CLI https://wasmtime.dev/
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/G5xIkF1OoV8vQ9q2G7wSqQ