TensorFlow.js 微信小程序插件開始支持 WebAssembly

我們知道,微信小程序由一個描述整體程序的 app 和多個描述各自頁面的 page 組成。小程序主體部分由 app.js、app.json、app.wxss三個文件組成,頁面 page 則通常包含 js、wxml、json、wxss 文件。這些文件都是文本文件,由微信小程序引擎解析並解釋執行。

然而,隨着業務需求越來越複雜,微信小程序的邏輯越來越複雜,相應的代碼量隨之變的越來越多。對於 js 代碼的執行,通常需要進行詞法分析 -> 語法分析 -> 預解析 -> 解釋執行等過程,性能太差。當然,隨着 JS 引擎在發展的過程中引入了許多優化手段如字節碼緩存,可以省掉每次解釋執行時重新遍歷語法樹的過程。特別是谷歌的 V8 的 JIT 技術,在運行過程中直接生成並緩存機器碼,下次執行時可由計算機直接執行,極大的提升了執行速度。然而,由於 JavaScript 這門語言本身的缺陷,使得優化變得越來越困難。由於JavaScript沒有靜態變量類型,只有動態變量,上一秒可能是Array,下一秒就變成了Object,那麼引擎所做的優化就失去了作用,這會導致運行效率降低。

爲了應對這一問題, WebAssembly 出現了。

WebAssembly

官方對 WebAssembly 的定義如下:

WebAssembly(wasm)是一個可移植、體積小、加載快並且兼容 Web 的全新格式。

嗯,估計你看了這個定義還是不知道 WebAssembly 是什麼。簡單來說,WebAssembly是一種新的字節碼格式,旨在成爲高級語言的編譯目標,目前可以使用C、C++、Rust、Go、Java、C#等編譯器(未來還有更多)來創建wasm模塊(見下圖)。該模塊以二進制的格式發送到瀏覽器,並在專有虛擬機上執行,與JavaScript虛擬機共享內存和線程等資源。

它是由 Google、Microsoft、Mozilla、Apple 等幾家大公司合作發起的一個關於面向Web的通用二進制和文本格式的項目。

關於字節碼格式,可以參考 Java,因爲 Java 程序就是一種與平臺無關的字節碼。

首先,字節碼是一種經過編譯器編譯之後的二進制代碼,無需經過解析字節碼編譯這兩步。其次,WebAssembly強制使用靜態類型,在語法上完全脫離JavaScript,同時具有沙盒化的執行環境,安全性更好。最後,WebAssembly可直接和html以及瀏覽器進行交互。

相對於 JS,WebAssembly 有如下優點:

  • 體積小:由於瀏覽器運行時只加載編譯成的字節碼,一樣的邏輯比用字符串描述的 JS 文件體積要小很多;

  • 加載快:由於文件體積小,再加上無需解釋執行,WebAssembly 能更快的加載並實例化,減少運行前的等待時間;

  • 兼容性問題少:WebAssembly 是非常底層的字節碼規範,制訂好後很少變動,就算以後發生變化,也只需在從高級語言編譯成字節碼過程中做兼容。可能出現兼容性問題的地方在於 JS 和 WebAssembly 橋接的 JS 接口。

微信小程序對WebAssembly的支持

微信小程序在Android / iOS上用於執行腳本以及渲染組件的環境都不盡相同。

在Android上,微信小程序的 Javascript 引擎採用了 V8,原生支持 WebAssembly,所以微信小程序在 Android 手機上提供 WebAssembly的支持。

在iOS上,微信小程序採用了蘋果公司的 JavaScriptCore 引擎,並沒有原生支持 WebAssembly,但最新 JavaScriptCore 也已經支持 WebAssembly。在不久的將來,IOS 手機 的微信小程序會支持 WebAssembly。

使用TensorFlow.js的WASM backend

TensorFlow.js的WASM backend非常適合在中低端Android手機上使用。中低端手機的GPU往往相對CPU要弱一些,而WASM backend是跑在CPU上的,這就爲中低端手機提供了另一個加速平臺。而且WASM的能耗一般會更低。使用WASM backend需要修改package.json文件:

{
  "name": "yourProject",
  "version": "0.0.1",
  "main": "dist/index.js",
  "license": "Apache-2.0",
  "dependencies": {
    "@tensorflow/tfjs-core": "1.7.3",
    "@tensorflow/tfjs-converter": "1.7.3",
    "@tensorflow/tfjs-backend-wasm": "1.7.3",
    ...
  }
}

然後在app.js中設置 wasm backend, 你可以自行在服務器上託管 wasm 文件以提高下載速度, 下面例子中的 wasmUrl 可以替代成你的URL。

const info = wx.getSystemInfoSync();
    const wasmUrl = 'https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]/wasm-out/tfjs-backend-wasm.wasm';
    const usePlatformFetch = true;
    console.log(info.platform);
    if (info.platform == 'android') {
      setWasmPath(wasmUrl, usePlatformFetch);
      tf.setBackend('wasm').then(() => console.log('set wasm backend'));
    }

注意 使用WASM需要導入>= 1.7.3的tfjs庫。

小結

本文介紹了 WebAssembly 以及微信小程序對 WebAssembly 的支持情況,最後介紹瞭如何啓用TensorFlow.js的WASM backend。由於在蘋果手機上還未能全面支持 WebAssembly,在加上 WebAssembly 技術出現的比較晚(2015年),需要時間的檢驗,要在項目中全面採用 WebAssembly 不現實。但是如果項目中某個功能模塊存在性能瓶頸,使用傳統的 JS 實現效率太低,這個時候可以考慮 WebAssembly。另外, 如果在低端 Android 手機上運行 tfjs 微信小程序,也可以考慮採用WASM backend。

參考

  1. https://github.com/tensorflow/tfjs-wechat

  2. WebAssembly進階系列一:WebAssembly是什麼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章