雖然專注在後端技術上,對前端只有初學者左右的程度,但還是多少對前端的技術很感興趣
而且這個技術對後端相對方便的,如果可以在前端技術上有更多精進的能力,多少可以解決更多問題
WebAssembly 簡介
WebAssembly 是一個以二進制表示的低階語言,可以在瀏覽器上運行,由於是二進制所以運行速度肯定會快點
特點則是說可以接近原生的效能,我個人觀點則是可以突破某些狀況下的限制和效能的提升,所以也有可能變慢囉!要謹慎使用
並且 2019 年時 WebAssembly正式成為W3C推薦的網頁應用標準
WebAssembly 與 JS 共存,輔助加強 JS 產生更多的應用並提升性能
目前可以使用 C/C++
、Go
、Rust
透過 Emscripten 編譯成 WebAssembly
WebAssembly - Go
Go 1.11 開始支援 WebAssembly 可以透過 Go 來進行開發
首先需要將 wasm_exec.js 複製到需專案目錄中,稍候需要 js 調用 wasm 檔案
|
|
Sample
寫個簡單的程式,先練練手培養的感覺
|
|
然後對此進行編譯,參數則是 GOOS=js
的 GOARCH=wasm
,稍候就可以透過 js 來呼叫 wasm
|
|
HTML
撰寫一個 index.html 引入 wasm_exec.js,然後透過 * JavaScript 使用 main.wasm 中的 function
|
|
目錄樹
.
├── go.mod
├── go.sum
├── index.html
├── main.go
├── main.wasm
└── wasm_exec.js
測試
測試需要一個簡易的 web server,官方推薦使用 goexec 來方便搭建 http 協議處理
|
|
然後在專案的環境中執行以下命令,就可以很快速的建立起簡單的 Web Server,可以拿來測試使用
|
|
透過瀏覽器訪問 http://127.0.0.1:8080,然後在瀏覽器中使用 F12 開啟開發者工具
在 Console 介面中觀看是否出現 Hello, WebAssembly!
進階測試
那就來寫一個加解密的功能看是否可以正常呼叫,之前在寫 Pairing-Based Cryptography 相關的程式的時候
當時實在是找不到 JS 的 Library 可以使用,所以當時弄了一個 API 進行呼叫,來測試看看是否能轉成 wasm
Demo
首先呢,想要將函式可以在瀏覽器中給 JS呼叫,這裡就要 import "syscall/js"
主要是讓 Go 可以與 JS 之間的變數型態可以相互溝通,並且讓 JS 可以呼叫 Go 的函式
然後設定 demo 的函式讓 JS 可以呼叫
|
|
再來就是將參數可以傳入 Go 的函式中進行使用,透過 args []js.Value
將參數傳入
而我這邊只傳入 明文m 這個參數並轉換成字串型別,所以只有 args[0].String()
在透過加密解密的過程,這邊則省略,若有興趣完整的程式碼在 github.com/cody0704/WebAssembly-example-go
是一個簡單 PBC 的加密、簽章的基本算法
|
|
然後一樣進行編譯,然後再運行簡易測試用的 Web Server
|
|
再度訪問 http://127.0.0.1:8080,並呼叫 demo 這個函式,看是否能正常使用
應用
看起來 WebAssembly 比較是用來進行比較複雜的運算,大多數應用在 遊戲、密碼加密、影音等等
畢竟大多數的功能還是可以由 JS 完成,貌似只有追求效能時,才會評估是否可以使用 WebAssembly
也可以將某些已經完成的功能可以快速移植到 wasm 使用,就不用再開發 JS 的版本
或者是有些 JS 本來就沒人開發的功能,直接編譯使用
效能
不過這樣可能也無法評斷出效能上的差異,takahirox.github.io/WebAssembly-benchmark
分別提供 JS 和 WebAssembly 的寫法,並且提供了各種的情境,可以從網頁上直接測試
當然不是全部都是 WebAssembly 比較快,還是需要適當的使用,以下是我測試出來的結果
- | JavaScript | WebAssembly | JavaScript/WebAssembly |
---|---|---|---|
collisionDetection | 456.3445 ms |
517.0255 ms | 0.8826 |
Fibonacci | 456.3445 ms |
517.0255 ms | 2.7034 |
ImageConvolute | 50.5980 ms | 40.1635 ms |
1.2598 |
ImageGrayscale | 1.4198 ms |
3.2808 ms | 0.4328 |
ImageThreshold | 7.6906 ms | 7.0060 ms |
1.0977 |
MultiplyInt | 947.4215 ms | 213.8170 ms |
4.4310 |
MultiplyDouble | 964.2590 ms | 577.9550 ms |
1.6684 |
MultiplyIntVec | 65.6780 ms |
97.9795 ms | 0.6703 |
MultiplyDoubleVec | 75.5460 ms |
170.6345 ms | 0.4427 |
QuicksortInt | 635.2805 ms | 413.1235 ms |
1.5377 |
QuicksortDouble | 309.5190 ms | 262.5270 ms |
1.1790 |
SumInt | 139.2075 ms |
163.4175 ms | 0.8519 |
SumDouble | 83.0160 ms |
162.4150 ms | 0.5111 |
VideoConvolute | 31.5505 ms | 22.4300 ms |
1.4066 |
VideoGrayscale | 0.9350 ms |
2.7695 ms | 0.3376 |
VideoMarkerDetection | 5.9095 ms |
5.9825 ms | 0.9878 |
VideoThreshold | 3.4204 ms |
4.2052 ms | 0.8134 |
結論
從性能在各種情境下的測試,可以大致上從表中來決定在什麼狀況下來使用 wasm 會提升性能
否則如果一味使用 wasm 搞不好會挖坑把自己埋了
然而還是可以看出有很多方便的用法,不過也擔心會變得很雜亂
不曉得哪些是呼叫 JS 哪些是從 wasm 呼叫的,需要再整理資料