自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

WebAssembly及其 API 的完整介紹

開發(fā) 后端
自從引入計算機(jī)以來,本地應(yīng)用程序的性能有了巨大的提高。相比之下,web 應(yīng)用程序相當(dāng)慢,因為 JS 一開始并不是為了速度而構(gòu)建的。但是由于瀏覽器之間的激烈競爭以及JS 引擎如V8的快速開發(fā),使得 JS 能夠在機(jī)器上快速運行。但是它仍然不能超過本機(jī)應(yīng)用程序的性能。這主要是因為 JS 代碼必須經(jīng)歷幾個進(jìn)程才能生成機(jī)器碼。

[[350065]]

自從引入計算機(jī)以來,本地應(yīng)用程序的性能有了巨大的提高。相比之下,web 應(yīng)用程序相當(dāng)慢,因為 JS 一開始并不是為了速度而構(gòu)建的。但是由于瀏覽器之間的激烈競爭以及JS 引擎如V8的快速開發(fā),使得 JS 能夠在機(jī)器上快速運行。但是它仍然不能超過本機(jī)應(yīng)用程序的性能。這主要是因為 JS 代碼必須經(jīng)歷幾個進(jìn)程才能生成機(jī)器碼。

隨著 WebAssembly 的引入,現(xiàn)代 Web 發(fā)生革命性的變化,這項技術(shù)非???。讓我們看一下什么是 WebAssembly,以及如何與 JS 集成以構(gòu)建快速的應(yīng)用程序。

什么是 WebAssembly?

在了解 WebAssembly 之前,讓我們看一下什么是 Assembly。

Assembly(匯編)是一種低級編程語言,它與體系結(jié)構(gòu)的機(jī)器級指令有著非常密切的聯(lián)系。換句話說,它只需一個進(jìn)程就可以轉(zhuǎn)換為機(jī)器可以理解的代碼,即機(jī)器代碼。此轉(zhuǎn)換過程稱為匯編。

WebAssembly可以簡稱為 Web 的匯編。它是一種類似于匯編語言的低級語言,具有緊湊的二進(jìn)制格式,使您能夠以類似本機(jī)的速度運行Web應(yīng)用程序。它還為C,C ++和Rust等語言提供了編譯目標(biāo),從而使客戶端應(yīng)用程序能夠以接近本地的性能在Web上運行。

此外,WebAssembly 的出現(xiàn)是與 JS 一起運行,而不是取代 JS。使用 WebAssembly JavaScript API,你可以交替地運行來自任一種語言的代碼,來回沒有任何問題。這為我們提供了利用 WebAssembly 的強大功能和性能以及 JS 的通用性和適應(yīng)性的應(yīng)用程序。這為web應(yīng)用程序打開了一個全新的世界,它可以運行最初并不打算用于web的代碼和功能。

有什么區(qū)別

Lin Clark預(yù)測,2017年 WebAssembly 的引入可能會引發(fā) web 開發(fā)生命中的一個新的拐點。早期的另一個拐點 生在引入 JITs 編譯的時候,JIT 編譯使JS 的速度提高了近10倍。

如果將 WebAssembly 的編譯過程與 JS 的編譯過程進(jìn)行比較,會注意到幾個過程已被剝離,其余過程已被修剪,如下所示:

JIT 是使 JavaScript 運行更快的一種手段,通過監(jiān)視代碼的運行狀態(tài),把 hot 代碼(重復(fù)執(zhí)行多次的代碼)進(jìn)行優(yōu)化。通過這種方式,可以使 JavaScript 應(yīng)用的性能提升很多倍。

仔細(xì)比較上圖,注意到,重新參與WebAssembly已經(jīng)完全被剝奪掉了。這主要是因為編譯器不需要對WebAssembly代碼做任何假設(shè),因為諸如數(shù)據(jù)類型是在代碼中明確提及。

但是 JS 不是這樣的,因為JIT應(yīng)該做一些假設(shè)來運行代碼,如果假設(shè)失敗,它需要重新優(yōu)化它的代碼。

如何獲取 WebAssembly 代碼

WebAssembly是一項偉大的技術(shù),我們需要如何利用 WebAssembly 的強大功能呢?

有幾種方法:

  • 不推薦從頭編寫 WebAssembly 代碼,除非你非常了解基本知識
  • 從 C 編譯為 WebAssembly
  • 從 C++ 編譯為 WebAssembly
  • 從 Rust 編譯為 WebAssembly
  • 使用 AssemblyScript 將 Typescript 編譯為WebAssembly。對于不熟悉C/C ++或Rust 的 Web開發(fā)人員來說,這是一個不錯的選擇
  • 支持更多的語言選項。

此外,還有Emscripten和WebAssembly Studio之類的工具可以幫助您完成上述過程。

JS 的 WebAssembly API

為了充分利用 WebAssembly 的特性,我們必須將其與 JS 代碼集成在一起,這可以在JavaScript WebAssembly API的幫助下完成。

模塊編譯和實例化

WebAssembly代 碼駐留在.wasm文件中。這個文件應(yīng)該被編譯成特定于它所運行的機(jī)器的機(jī)器碼。我們可以使用WebAssembly.compile方法來編譯 WebAssembly 模塊。

WebAssembly.instantiate方法實例化已編譯模塊。另外,我們也可以從.wasm文件獲得的數(shù)組緩沖區(qū)傳遞到WebAssembly.instantiate方法中。這也適用,因為實例化方法有兩個重載。

  1. let exports 
  2.  
  3. fetch('sample.wasm').then(response => 
  4.   response.arrayBuffer() 
  5. ).then(bytes => 
  6.   WebAssembly.instantiate(bytes) 
  7. ).then(results => { 
  8.   exports = results.instance.exports 
  9. }) 

上述方法的缺點之一是這些方法不能直接訪問字節(jié)碼,因此在編譯/實例化wasm模塊之前,需要采取額外的步驟將響應(yīng)轉(zhuǎn)換為ArrayBuffer。

相反,我們可以使用WebAssembly.compileStreaming / WebAssembly.instantiateStreaming方法來實現(xiàn)與上述相同的功能,其優(yōu)點是可以直接訪問字節(jié)碼,而無需將響應(yīng)轉(zhuǎn)換為ArrayBuffer。

  1. let exports 
  2.  
  3. WebAssembly.instantiateStreaming(fetch('sample.wasm')) 
  4. .then(obj => { 
  5.   exports = obj.instance.exports 
  6. }) 

注意,WebAssembly.instantiate和WebAssembly.instantiateStreaming會返回實例以及已編譯的模塊,它們可用于快速啟動模塊的實例。

  1. let exports; 
  2. let compiledModule; 
  3.  
  4. WebAssembly.instantiateStreaming(fetch('sample.wasm')) 
  5. .then(obj => { 
  6.   exports = obj.instance.exports; 
  7.   //access compiled module 
  8.   compiledModule = obj.module; 
  9. }) 

導(dǎo)入對象

實例化 WebAssembly 模塊實例時,可以選擇傳遞一個導(dǎo)入對象,該對象將包含要導(dǎo)入到新創(chuàng)建的模塊實例中的值,有 4 種類型:

  • global values
  • functions
  • memory
  • tables

可以將導(dǎo)入對象視為提供給模塊實例的工具,以幫助它實現(xiàn)其任務(wù)。如果沒有提供導(dǎo)入對象,編譯器將分配默認(rèn)值。

Global

WebAssembly.Global 對象表示一個全局變量實例, 可以被JavaScript 和importable/exportable 訪問 ,跨越一個或多個WebAssembly.Module 實例. 他允許被多個modules動態(tài)連接.

可以使用WebAssembly.Global()構(gòu)造函數(shù)創(chuàng)建全局實例。

  1. const global = new WebAssembly.Global({ 
  2.     value: 'i64'
  3.     mutable: true 
  4. }, 20) 

語法

  1. var myGlobal = new WebAssembly.Global(descriptor, value) 

global 構(gòu)造函數(shù)接受兩個參數(shù)。

descriptor

GlobalDescriptor 包含2個屬性的表:

  • value: A USVString 表示全局變量的數(shù)據(jù)類型. 可以是i32, i64, f32, 或 f64
  • mutable: 布爾值決定是否可以修改. 默認(rèn)是 false

value可以是任意變量值,需要其類型與變量類型匹配. 如果變量沒有定義, 使用0代替

  1. const global = new WebAssembly.Global({ 
  2.     value: 'i64'
  3.     mutable: true 
  4. }, 20); 
  5.  
  6. let importObject = { 
  7.     js: { 
  8.         global 
  9.     } 
  10. }; 
  11.  
  12. WebAssembly.instantiateStreaming(fetch('global.wasm'), importObject) 

全局實例應(yīng)該傳遞給importObject,以便在 WebAssembly 模塊實例中可以訪問它。

Memory

當(dāng) WebAssembly 模塊被實例化時,它需要一個 memory 對象。你可以創(chuàng)建一個新的WebAssembly.Memory并傳遞該對象。如果沒有創(chuàng)建 memory 對象,在模塊實例化的時候?qū)詣觿?chuàng)建,并且傳遞給實例。

JS引擎創(chuàng)建一個ArrayBuffer來做這件事情。ArrayBuffer 是 JS 引用的 JavaScript 對象。JS 為你分配內(nèi)存。你告訴它需要多少內(nèi)存,它會創(chuàng)建一個對應(yīng)大小的ArrayBuffer

ArrayBuffer 做了兩件事情,一件是做 WebAssembly 的內(nèi)存,另外一件是做 JavaScript 的對象。

它使 JS 和 WebAssembly 之間傳遞內(nèi)容更方便。

使內(nèi)存管理更安全。

Table

WebAssembly.Table() 構(gòu)造函數(shù)根據(jù)給定的大小和元素類型創(chuàng)建一個Table對象。

這是一個包裝了WebAssemble Table 的Javascript包裝對象,具有類數(shù)組結(jié)構(gòu),存儲了多個函數(shù)引用。在 JS 或者WebAssemble中創(chuàng)建Table 對象可以同時被JS 或WebAssemble 訪問和更改。

引入Table的主要原因是提高了安全性。我們可以使用set()、grow()和get()方法來操作表。

事例

為了演示,我將使用WebAssembly Studio應(yīng)用程序?qū)文件編譯為.wasm。

我已經(jīng)在wasm文件中創(chuàng)建了一個函數(shù)來計算一個數(shù)字的冪。我將必要的值傳遞給函數(shù),然后用JavaScript接收輸出。

同樣,我在wasm中進(jìn)行了一些字符串操作。需要注意,wasm沒有字符串類型。因此,它將使用ASCII值。返回到 JS 的值將指向存儲輸出的內(nèi)存位置。由于內(nèi)存對象是ArrayBuffer,因此我要進(jìn)行迭代,直到收到字符串中的所有字符為止。

JavaScript文件

  1. let exports; 
  2. let buffer; 
  3. (async() => { 
  4.   let response = await fetch('../out/main.wasm'); 
  5.   let results = await WebAssembly.instantiate(await response.arrayBuffer()); 
  6.   //or 
  7.   // let results = await WebAssembly.instantiateStreaming(fetch('../out/main.wasm')); 
  8.   let instance = results.instance; 
  9.   exports = instance.exports; 
  10.   buffer = new Uint8Array(exports.memory.buffer); 
  11.  
  12.   findPower(5,3); 
  13.    
  14.   printHelloWorld(); 
  15.    
  16. })(); 
  17.  
  18. const findPower = (base = 0, power = 0) => { 
  19.   console.log(exports.power(base,power)); 
  20.  
  21. const printHelloWorld = () => { 
  22.   let pointer = exports.helloWorld(); 
  23.   let str = ""
  24.   for(let i = pointer;buffer[i];i++){ 
  25.     str += String.fromCharCode(buffer[i]); 
  26.   } 
  27.   console.log(str); 

C 文件

  1. #define WASM_EXPORT __attribute__((visibility("default"))) 
  2. #include <math.h> 
  3.  
  4.  
  5. WASM_EXPORT 
  6. double power(double number,double power_value) { 
  7.   return pow(number,power_value); 
  8.  
  9. WASM_EXPORT 
  10. char* helloWorld(){ 
  11.   return "hello world"

應(yīng)用

WebAssembly 更適合用于寫模塊,承接各種復(fù)雜的計算,如圖像處理、3D運算、語音識別、視音頻編碼解碼這種工作,主體程序還是要用 javascript 來寫的。

可以找我返現(xiàn)15(https://cn.aliyun.com/1111/home?userCode=pxuujn3r)

作者:Mahdhi Rezvi 譯者:前端小智 來源:medium

原文:https://blog.bitsrc.io/a-complete-introduction-to-webassembly-and-its-javascript-api-3474a9845206 11111

菜v菜  本文轉(zhuǎn)載自微信公眾號「大遷世界」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系大遷世界公眾號。

 

責(zé)任編輯:武曉燕 來源: 大遷世界
相關(guān)推薦

2023-12-10 16:48:00

Wasm瀏覽器

2017-03-19 20:41:57

WebAssemblyJavaScript編程

2021-12-27 10:46:07

WebAPIserver簽名

2009-11-23 20:03:18

ibmdwLotus

2012-08-02 09:18:05

LESSSassCSS

2017-03-19 22:13:10

WebAssemblyJavaScript編程

2009-08-06 18:02:22

存儲過程

2010-10-09 08:50:16

2009-04-02 13:45:36

網(wǎng)關(guān)網(wǎng)絡(luò)

2009-06-19 18:42:06

jBPMSSH

2017-03-19 22:43:12

WebAssemblyJavaScript編程

2011-12-20 11:20:46

PhoneGap APCompass

2011-12-19 16:09:32

PhoneGap APCamera

2011-12-19 15:30:25

AccelerometPhoneGap AP

2011-12-20 15:34:55

PhoneGap APConnection

2011-12-20 17:15:52

PhoneGap APEvents

2011-12-22 10:33:39

PhoneGap APNotificatio

2011-12-22 10:45:32

PhoneGap APStorage

2011-12-21 21:56:45

PhoneGap APFile

2011-12-19 16:26:39

PhoneGap APCapture
點贊
收藏

51CTO技術(shù)棧公眾號