WebAssembly 陣列傳遞(輸出篇)
阿新 • • 發佈:2019-01-29
最近有一個專案需要以原生方式輸出js陣列,這裡分類一些方法:
公共頭部:
#include <emscripten/val.h>
#include <emscripten/bind.h>
using namespace emscripten;
*注意:在使用emscripten::val和emscripten::bind時,編譯時要帶上--bind引數
耗時對比:
(以傳輸1,580,000個double資料為例,資料單位:毫秒)
方法1:
查閱文件可知,val就是代表的js裡的原生資料型別。
通過val::array()就能構造陣列,通過.set方法可以設定資料內容
所以最初始的辦法就是直接使用for迴圈複製
val get1XArray(double *arr, int len){
val ret = val::array();
for(int i = 0; i < len; i ++) ret.set(i, arr[i]);
return ret;
}
優點:簡單、直觀、可擴充套件
缺點:記憶體中不連續造成定址時間長
方法2:
上面這種方法由於陣列長度不固定,造成了記憶體浪費,解決方法就是使用TypedArray(對應double的是Float64Array)
查閱文件可知,通過val::global能取得js全域性物件,.new_方法新建例項
改寫後:
val get1XArray(double *arr, int len){
val ret = val::global("Float64Array").new_(len); //js: new Float64Array(len)
for(int i = 0; i < len; i ++) ret.set(i, arr[i]);
return ret;
}
但是這樣速度反而更慢了,可能是因為new操作很耗時
好處是記憶體利用率提高了
方法3:
之後在想辦法解決速度問題時,發現了文件的例項裡有一個typed_memory_view(length, array)函式
(吐槽一下,文件裡沒找到這個函式的解釋,官方文件不認真啊)
所以最終改寫版:
val get1XArray(double *arr, int len){
return val(typed_memory_view(len, arr));
}
優點:速度上的飛躍,原先需要1200ms才能轉換的資料,現在大概只要7ms
缺點:輸出型別為對應的TypedArray,需要動態長度陣列的不能用
傳輸二維陣列的方法:
val get2XArray(double **arr, int y_len, int x_len){
val ret = val::array();
for(int i = 0; i < y_len; i ++){
ret.set(i, val(typed_memory_view(x_len, arr[i])));
}
return ret;
}
另:
因為目前還沒有wasm的群,所以自己建了個:866749590
有問題可以相互幫助