欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

WebAssembly使用方法研究

 更新時(shí)間:2023年08月08日 14:23:00   作者:郝同學(xué)1208  
這篇文章主要為大家介紹了WebAssembly使用方法研究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

之前在瀏覽前端技術(shù)的時(shí)候留意到了webAssembly這項(xiàng)技術(shù),看到它是類似于在前端調(diào)用后端語言的源碼或者說功能,再加上筆者淺學(xué)過C++和java,故在此做一些調(diào)研和嘗試

什么是WebAssembly

WebAssembly以下簡稱WASM,通過將傳統(tǒng)意義上的后端語言(C、C++、Java、Rust等)編譯成字節(jié)碼,.wasm格式文件,在瀏覽器上調(diào)用解釋器編譯成機(jī)器碼才能運(yùn)行,因此WASM并不能真正達(dá)到匯編語言級(jí)別的性能,與Java比較像,都是編譯成中間字節(jié)碼,然后交由解釋器工作(在Java中則是JVM)。

2015年4月,WebAssembly Community Group 成立;

2015年6月,WebAssembly第一次以WCG的官方名義向外界公布;

2016年8月,WebAssembly開始進(jìn)入了漫長的“Browser Preview”階段;

2017年2月,WebAssembly官方LOGO在Github上的眾多討論中被最終確定;同年同月,一個(gè)歷史性的階段,四大瀏覽器(FireFox、Chrome、Edge、WebKit)在WebAssembly的MVP(最小可用版本)標(biāo)準(zhǔn)實(shí)現(xiàn)上達(dá)成共識(shí),這意味著WebAssembly在其MVP標(biāo)準(zhǔn)上的“Brower Preview”階段已經(jīng)結(jié)束;

2017年8月,W3C WebAssembly Working Group 成立,意味著WebAssembly正式成為W3C眾多技術(shù)標(biāo)準(zhǔn)中的一員。

2019年12月,WebAssembly成為萬維網(wǎng)聯(lián)盟(W3C)的推薦標(biāo)準(zhǔn),與HTML,CSS和JavaScript一起成為Web的第四種語言。

使用方法

從.wasm源文件到實(shí)例化的對(duì)象主要有三個(gè)步驟,加載->編譯->實(shí)例化->調(diào)用。

加載:讀取.wasm字節(jié)碼到本地中,一般是通過請(qǐng)求從網(wǎng)絡(luò)中取得。

編譯:在Worker線程進(jìn)行,編譯成平臺(tái)相關(guān)的代碼。

實(shí)例化:將宿主環(huán)境的一些對(duì)象、方法導(dǎo)入到wasm模塊中,比如導(dǎo)入操作dom的方法。

調(diào)用:通過上一步已經(jīng)實(shí)例化的對(duì)象,來調(diào)用wasm模塊中的方法。主要有兩種類型的API,一種是js提供的api,另一種是Web提供的api,Web提供的api支持流式編譯實(shí)例化。

js的方法,WebAssembly.instantiate(bufferSource,importObject),可以完成編譯和實(shí)例化。

bufferSource是含有效Wasm模塊二進(jìn)制字節(jié)碼的ArrayBuffer或TypedArray對(duì)象。importObject是要導(dǎo)入到Wasm模塊中的對(duì)象。方法在調(diào)用后返回一個(gè)Promise對(duì)象,resolve后返回一個(gè)對(duì)象,該對(duì)象包含編譯好的module和已經(jīng)實(shí)例化的instance,模塊導(dǎo)出的方法可以通過instance對(duì)象進(jìn)行調(diào)用。

web的方法,WebAssembly.instantiateStreaming(source,importObject)。不同之處在于第一個(gè)參數(shù),這里的source指的是尚未Resolve的Response對(duì)象(window.fetch調(diào)用后會(huì)返回該對(duì)象),好處就是可以邊讀取.wasm字節(jié)流,邊進(jìn)行編譯。其他參數(shù)和返回值和js的api均一致。

jsAPI嘗試

先簡單的嘗試一下,我們直接構(gòu)造一個(gè)wasm模塊的TypedArray對(duì)象,該模塊包含了一個(gè)add方法,然后調(diào)用WebAssembly.instantiate進(jìn)行編譯和實(shí)例化。對(duì)應(yīng)的C++代碼。

#include <emscripten.h>
extern "C" {
  EMSCRIPTEN_KEEPALIVE 
  int add(int a, int b) {
    return a + b;
  }
}
對(duì)應(yīng)的.wasm字節(jié)碼:
00 61 73 6D 01 00 00 00 01 17 05 60 00 01 7F 60
00 00 60 01 7F 00 60 01 7F 01 7F 60 02 7F 7F 01
7F 03 07 06 01 04 00 02 03 00 04 05 01 70 01 02
02 05 06 01 01 80 02 80 02 06 0F 02 7F 01 41 90
88 C0 02 0B 7F 00 41 84 08 0B 07 82 01 09 06 6D
65 6D 6F 72 79 02 00 19 5F 5F 69 6E 64 69 72 65
63 74 5F 66 75 6E 63 74 69 6F 6E 5F 74 61 62 6C
65 01 00 03 61 64 64 00 01 0B 5F 69 6E 69 74 69
61 6C 69 7A 65 00 00 10 5F 5F 65 72 72 6E 6F 5F
6C 6F 63 61 74 69 6F 6E 00 05 09 73 74 61 63 6B
53 61 76 65 00 02 0C 73 74 61 63 6B 52 65 73 74
6F 72 65 00 03 0A 73 74 61 63 6B 41 6C 6C 6F 63
00 04 0A 5F 5F 64 61 74 61 5F 65 6E 64 03 01 09
07 01 00 41 01 0B 01 00 0A 30 06 03 00 01 0B 07
00 20 00 20 01 6A 0B 04 00 23 00 0B 06 00 20 00
24 00 0B 10 00 23 00 20 00 6B 41 70 71 22 00 24
00 20 00 0B 05 00 41 80 08 0B
然后直接在控制臺(tái)輸入下邊的代碼:
WebAssembly.instantiate(new Uint8Array(`
  00 61 73 6D 01 00 00 00 01 17 05 60 00 01 7F 60
00 00 60 01 7F 00 60 01 7F 01 7F 60 02 7F 7F 01
7F 03 07 06 01 04 00 02 03 00 04 05 01 70 01 02
02 05 06 01 01 80 02 80 02 06 0F 02 7F 01 41 90
88 C0 02 0B 7F 00 41 84 08 0B 07 82 01 09 06 6D
65 6D 6F 72 79 02 00 19 5F 5F 69 6E 64 69 72 65
63 74 5F 66 75 6E 63 74 69 6F 6E 5F 74 61 62 6C
65 01 00 03 61 64 64 00 01 0B 5F 69 6E 69 74 69
61 6C 69 7A 65 00 00 10 5F 5F 65 72 72 6E 6F 5F
6C 6F 63 61 74 69 6F 6E 00 05 09 73 74 61 63 6B
53 61 76 65 00 02 0C 73 74 61 63 6B 52 65 73 74
6F 72 65 00 03 0A 73 74 61 63 6B 41 6C 6C 6F 63
00 04 0A 5F 5F 64 61 74 61 5F 65 6E 64 03 01 09
07 01 00 41 01 0B 01 00 0A 30 06 03 00 01 0B 07
00 20 00 20 01 6A 0B 04 00 23 00 0B 06 00 20 00
24 00 0B 10 00 23 00 20 00 6B 41 70 71 22 00 24
00 20 00 0B 05 00 41 80 08 0B`.trim().split(/[\s\r\n]+/g).map(str => parseInt(str, 16))
)).then(({instance}) => {
  const { add } = instance.exports
  console.log('2 + 4 =', add(2, 4))
})
輸出2 + 4 = 6

WebAPI嘗試

我們?cè)賴L試一下流式編譯。直接使用之前的斐波納契數(shù)字的fibonacci.wasm模塊。首先我們需要提供一個(gè)簡單的HTTP服務(wù),用來返回.wasm文件。新建一個(gè)node.js文件。

const http = require('http');
const url = require('url');
const fs = require('fs');
const path = require('path');
const PORT = 8888;  // 服務(wù)器監(jiān)聽的端口號(hào);
const mime = {
  "html": "text/html;charset=UTF-8",
  "wasm": "application/wasm"  //當(dāng)遇到對(duì)".wasm"格式文件的請(qǐng)求時(shí),返回特定的MIME頭;
};
http.createServer((req, res) => {
  let realPath = path.join(__dirname, `.${url.parse(req.url).pathname}`);
  //檢查所訪問文件是否存在,且是否可讀;
  fs.access(realPath, fs.constants.R_OK, err => {  
    if (err) {
      res.writeHead(404, { 'Content-Type': 'text/plain' });
      res.end();
    } else {
      fs.readFile(realPath, "binary", (err, file) => {
        if (err) {
          //文件讀取失敗時(shí)返回500;
          res.writeHead(500, { 'Content-Type': 'text/plain' });
          res.end();
        } else {
          //根據(jù)請(qǐng)求的文件返回相應(yīng)的文件內(nèi)容;
          let ext = path.extname(realPath);
          ext = ext ? ext.slice(1) : 'unknown';
          let contentType = mime[ext] || "text/plain";
          res.writeHead(200, { 'Content-Type': contentType });
          res.write(file, "binary");
          res.end();
        }
      });
    }
  });
}).listen(PORT);
console.log("Server is runing at port: " + PORT + ".");

然后來編寫我們的js部分,講到斐波那契數(shù)字,我們順便做一個(gè)性能的測試,來比較一下使用wasm的方式和原生js的求解速度。

function fibonacciJS(n) {
  if (n < 2) {
    return 1;
  }
  return fibonacciJS(n - 1) + fibonacciJS(n - 2);
}
const response = fetch("fibonacci.wasm");
const num = [5, 15, 25, 35, 45];
WebAssembly.instantiateStreaming(response).then(
  ({ instance }) => {
    let { fibonacci } = instance.exports;
    for(let n of num) {
      console.log(`斐波納切數(shù)字: ${n},運(yùn)行 10 次`)
      let cTime = 0;
      let jsTime = 0;
      for(let time = 0; time < 10; time++) {
        let start = performance.now();
        fibonacci(n)
        cTime += (performance.now() - start)
        start = performance.now();
        fibonacciJS(n)
        jsTime += (performance.now() - start)
      }
      console.log(`wasm 模塊平均調(diào)用時(shí)間:${cTime / 10}ms`)
      console.log(`js 模塊平均調(diào)用時(shí)間:${jsTime / 10}ms`)
    }
  }
)

然后執(zhí)行node node.js開啟http服務(wù),接著在瀏覽器中打開http://localhost:8888/index.html,控制臺(tái)中輸出如下:

斐波納切數(shù)字: 5,運(yùn)行 10 次
index.html:34 wasm 模塊平均調(diào)用時(shí)間:0.001499993959441781ms
index.html:35 js 模塊平均調(diào)用時(shí)間:0.005500001134350896ms
index.html:22 斐波納切數(shù)字: 15,運(yùn)行 10 次
index.html:34 wasm 模塊平均調(diào)用時(shí)間:0.005999993300065398ms
index.html:35 js 模塊平均調(diào)用時(shí)間:0.15650001005269587ms
index.html:22 斐波納切數(shù)字: 25,運(yùn)行 10 次
index.html:34 wasm 模塊平均調(diào)用時(shí)間:0.6239999900572002ms
index.html:35 js 模塊平均調(diào)用時(shí)間:1.1620000121183693ms
index.html:22 斐波納切數(shù)字: 35,運(yùn)行 10 次
index.html:34 wasm 模塊平均調(diào)用時(shí)間:70.59700000681914ms
index.html:35 js 模塊平均調(diào)用時(shí)間:126.21099999523722ms
index.html:22 斐波納切數(shù)字: 45,運(yùn)行 10 次
index.html:34 wasm 模塊平均調(diào)用時(shí)間:8129.7520000021905ms
index.html:35 js 模塊平均調(diào)用時(shí)間:16918.658500007587ms

可以看到wasm很明顯的提高了運(yùn)行速度,運(yùn)行時(shí)間穩(wěn)定在js的一半,當(dāng)規(guī)模達(dá)到45的時(shí)候,wasm的運(yùn)行時(shí)間比js少了整整8秒。
這里也可以看出,如果對(duì)于計(jì)算密集型的應(yīng)用,wasm可以大展身手了,因此WASM適合運(yùn)用于游戲、視頻處理、AR等方面。

不止于WebWasm

除了應(yīng)用在瀏覽器中,也可以應(yīng)用到out-of-web環(huán)境中。通過WASI(WebAssembly System Interface,Wasm操作系統(tǒng)接口)標(biāo)準(zhǔn),Wasm可以直接與操作系統(tǒng)打交道。通過已經(jīng)在各種環(huán)境實(shí)現(xiàn)了WASI標(biāo)準(zhǔn)的虛擬機(jī),我們就可以將wasm用在嵌入式、IOT物聯(lián)網(wǎng)以及甚至云,AI和區(qū)塊鏈等特殊的領(lǐng)域和場景中。
有了WASI標(biāo)準(zhǔn),文章最開始介紹的當(dāng)前應(yīng)用的架構(gòu)在未來可能會(huì)發(fā)生質(zhì)的改變。
上邊架構(gòu)的最大問題就是各個(gè)操作系統(tǒng)不能兼容,同一個(gè)app需要采用不同的語言在不同平臺(tái)下各實(shí)現(xiàn)一次。比如一款A(yù)應(yīng)用,如果想實(shí)現(xiàn)跨平臺(tái)的話,我們需要用java完成在安卓上的開發(fā),用Objective-C實(shí)現(xiàn)iOS上的開發(fā),用C#實(shí)現(xiàn)PC端的開發(fā)...但如果有了wasm,我們只需要選擇任意一門語言,然后編譯成wasm,就可以分發(fā)到各個(gè)平臺(tái)上了。

總結(jié)

目前來講WASM在瀏覽器性能上和JS能打個(gè)55開,互有勝負(fù),WASM有他擅長的地方,JS有JS優(yōu)勢的地方,我認(rèn)為WASM并不會(huì)替代JS/TS,WASM的統(tǒng)一和整合,正如下圖

將所有的開發(fā)語言和所有的運(yùn)行環(huán)境連接起來,只不過因?yàn)閣eb天生的多平臺(tái)性,目前在web端應(yīng)用比較成熟,而這也確實(shí)在某些業(yè)務(wù)上能夠讓前端直接去調(diào)用C++的相關(guān)代碼。

但是就目前來講,你指望一個(gè)前端工程師為了性能優(yōu)化的原因,去學(xué)習(xí)C++然后再編寫C++代碼編譯成.wasm二進(jìn)制文件再放到瀏覽器環(huán)境上運(yùn)行?不可能的,所以目前WASM的應(yīng)用主要還是在JS沒有相應(yīng)合適的三方庫的情況下,去借用C++等后端語言的三方庫,比如視頻處理中的ffmpeg;或者將一部分后端的邏輯處理放到前端,減少服務(wù)壓力,不過這也是很沒必要。

我認(rèn)為,WASM目前階段已經(jīng)具備了很多成熟的應(yīng)用,而且未來可期,作為未來的技術(shù)方向有必要了解一下。

以上就是WebAssembly使用方法研究的詳細(xì)內(nèi)容,更多關(guān)于WebAssembly使用方法的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論