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

當(dāng)前 WebAssembly 的狀況

開發(fā) 開發(fā)工具
這篇文章介紹WebAssembly 工作原理以及為什么 WebAssembly 運(yùn)行的更快。

上一篇文章《關(guān)于WebAssembly 的背景知識》讓大家基本了解了 WebAssembly ,接下來我們繼續(xù)介紹WebAssembly 工作原理以及為什么 WebAssembly 運(yùn)行的更快。

一、WebAssembly 工作原理

WebAssembly 是除了 JavaScript 以外,另一種可以在網(wǎng)頁中運(yùn)行的編程語言。過去如果你想在瀏覽器中運(yùn)行代碼來對網(wǎng)頁中各種元素進(jìn)行控制,只有 JavaScript 這一種選擇。

所以當(dāng)人們談?wù)?WebAssembly 的時(shí)候,往往會(huì)拿 JavaScript 來進(jìn)行比較。但是它們其實(shí)并不是“二選一”的關(guān)系——并不是只能用 WebAssembly 或者 JavaScript。

實(shí)際上,我們鼓勵(lì)開發(fā)者將這兩種語言一起使用,即使你不親自實(shí)現(xiàn) WebAssembly 模塊,你也可以學(xué)習(xí)它現(xiàn)有的模塊,并它的優(yōu)勢來實(shí)現(xiàn)你的功能。

WebAssembly 模塊定義的一些功能可以通過 JavaScript 來調(diào)用。所以就像你通過 npm 下載 lodash 模塊并通過 API 使用它一樣,未來你也可以下載 WebAssembly 模塊并且使用其提供的功能。

那么,就讓我們來看一下如何開發(fā) WebAssembly 模塊,以及如何通過 JavaScript 使用他們。

1. WebAssembly 處于哪個(gè)環(huán)節(jié)?

上一篇關(guān)于WebAssembly 背景知識的文章中,我介紹了編譯器是如何從高級語言翻譯到機(jī)器碼的。

那么在上圖中,WebAssembly 在什么位置呢?實(shí)際上,你可以把它看成另一種“目標(biāo)匯編語言”。

每一種目標(biāo)匯編語言(x86、ARM)都依賴于特定的機(jī)器結(jié)構(gòu)。當(dāng)你想要把你的代碼放到用戶的機(jī)器上執(zhí)行的時(shí)候,你并不知道目標(biāo)機(jī)器結(jié)構(gòu)是什么樣的。

而 WebAssembly 與其他的匯編語言不一樣,它不依賴于具體的物理機(jī)器??梢猿橄蟮乩斫獬伤歉拍顧C(jī)器的機(jī)器語言,而不是實(shí)際的物理機(jī)器的機(jī)器語言。

正因?yàn)槿绱耍琖ebAssembly 指令有時(shí)也被稱為虛擬指令。它比 JavaScript 代碼更直接地映射到機(jī)器碼,它也代表了“如何能在通用的硬件上更有效地執(zhí)行代碼”的一種理念。所以它并不直接映射成特定硬件的機(jī)器碼。

WebAssembly 指令有時(shí)也被稱為虛擬指令

瀏覽器把 WebAssembly 下載下來后,可以迅速地將其轉(zhuǎn)換成機(jī)器匯編代碼。

2. 編譯到 .wasm 文件

目前對于 WebAssembly 支持情況***的編譯器工具鏈?zhǔn)?LLVM。有很多不同的前端和后端插件可以用在 LLVM 上。

提示:很多 WebAssembly 開發(fā)者用 C 語言或者 Rust 開發(fā),再編譯成 WebAssembly。其實(shí)還有其他的方式來開發(fā) WebAssembly 模塊。例如利用 TypeScript 開發(fā) WebAssembly 模塊,或者直接用文本格式的 WebAssembly 也可以。

假設(shè)想從 C 語言到 WebAssembly,我們就需要 clang 前端來把 C 代碼變成 LLVM 中間代碼。當(dāng)變換成了 LLVM IR 時(shí),說明 LLVM 已經(jīng)理解了代碼,它會(huì)對代碼自動(dòng)地做一些優(yōu)化。

為了從 LLVM IR 生成 WebAssembly,還需要后端編譯器。在 LLVM 的工程中有正在開發(fā)中的后端,而且應(yīng)該很快就開發(fā)完成了,現(xiàn)在這個(gè)時(shí)間節(jié)點(diǎn),暫時(shí)還看不到它是如何起作用的。

還有一個(gè)易用的工具,叫做 Emscripten。它通過自己的后端先把代碼轉(zhuǎn)換成自己的中間代碼(叫做 asm.js),然后再轉(zhuǎn)化成 WebAssembly。實(shí)際上它背后也是使用的 LLVM。

Emscripten 還包含了許多額外的工具和庫來包容整個(gè) C/C++ 代碼庫,所以它更像是一個(gè)軟件開發(fā)者工具包(SDK)而不是編譯器。例如系統(tǒng)開發(fā)者需要文件系統(tǒng)以對文件進(jìn)行讀寫,Emscripten 就有一個(gè) IndexedDB 來模擬文件系統(tǒng)。

不考慮太多的這些工具鏈,只要知道最終生成了 .wasm 文件就可以了。后面我會(huì)介紹 .wasm 文件的結(jié)構(gòu),在這之前先一起了解一下在 JS 中如何使用它。

3. 加載一個(gè) .wasm 模塊到 JavaScript

.wasm 文件是 WebAssembly 模塊,它可以加載到 JavaScript 中使用,現(xiàn)階段加載的過程稍微有點(diǎn)復(fù)雜。

  1. function fetchAndInstantiate(url, importObject) { 
  2.   return fetch(url).then(response => 
  3.     response.arrayBuffer() 
  4.   ).then(bytes => 
  5.     WebAssembly.instantiate(bytes, importObject) 
  6.   ).then(results => 
  7.     results.instance 
  8.   ); 

如果想深入了解,可以在 MDN 文檔中了解更多。

我們一直在致力于把這一過程變得簡單,對工具鏈進(jìn)行優(yōu)化。希望能夠把它整合到現(xiàn)有的模塊打包工具中,比如 webpack 中,或者整合到加載器中,比如 SystemJS 中。我們相信加載 WebAssembly 模塊也可以像加載 JavaScript 一樣簡單。

這里介紹 WebAssembly 模塊和 JavaScript 模塊的主要區(qū)別。當(dāng)前的 WebAssembly 只能使用數(shù)字(整型或者浮點(diǎn)型)作為參數(shù)或者返回值。

對于任何其他的復(fù)雜類型,比如 string,就必須得用 WebAssembly 模塊的內(nèi)存操作了。如果是經(jīng)常使用 JavaScript,對直接操作內(nèi)存不是很熟悉的話,可以回想一下 C、C++ 和 Rust 這些語言,它們都是手動(dòng)操作內(nèi)存。WebAssembly 的內(nèi)存操作和這些語言的內(nèi)存操作很像。

為了實(shí)現(xiàn)這個(gè)功能,它使用了 JavaScript 中稱為 ArrayBuffer 的數(shù)據(jù)結(jié)構(gòu)。ArrayBuffer 是一個(gè)字節(jié)數(shù)組,所以它的索引(index)就相當(dāng)于內(nèi)存地址了。

如果你想在 JavaScript 和 WebAssembly 之間傳遞字符串,可以利用 ArrayBuffer 將其寫入內(nèi)存中,這時(shí)候 ArrayBuffer 的索引就是整型了,可以把它傳遞給 WebAssembly 函數(shù)。此時(shí),***個(gè)字符的索引就可以當(dāng)做指針來使用。

這就好像一個(gè) web 開發(fā)者在開發(fā) WebAssembly 模塊時(shí),把這個(gè)模塊包裝了一層外衣。這樣其他使用者在使用這個(gè)模塊的時(shí)候,就不用關(guān)心內(nèi)存管理的細(xì)節(jié)。

如果你想了解更多的內(nèi)存管理,看一下我們寫的 WebAssembly 的內(nèi)存操作。

4. .wasm 文件結(jié)構(gòu)

如果你是寫高級語言的開發(fā)者,并且通過編譯器編譯成 WebAssembly,那你不用關(guān)心 WebAssembly 模塊的結(jié)構(gòu)。但是了解它的結(jié)構(gòu)有助于你理解一些基本問題。

如果你對編譯器還不了解,建議先讀一下“系列三之編譯器如何生成匯編這篇文章。

這段代碼是即將生成 WebAssembly 的 C 代碼:

  1. int add42(int num) { 
  2.     return num + 42; 

你可以使用 WASM Explorer 來編譯這個(gè)函數(shù)。

打開 .wasm 文件(假設(shè)你的編輯器支持的話),可以看到下面代碼:

  1. 00 61 73 6D 0D 00 00 00 01 86 80 80 80 00 01 60 
  2. 01 7F 01 7F 03 82 80 80 80 00 01 00 04 84 80 80 
  3. 80 00 01 70 00 00 05 83 80 80 80 00 01 00 01 06 
  4. 81 80 80 80 00 00 07 96 80 80 80 00 02 06 6D 65 
  5. 6D 6F 72 79 02 00 09 5F *** 35 61 64 64 34 32 69 
  6. 00 00 0A 8D 80 80 80 00 01 87 80 80 80 00 00 20 
  7. 00 41 2A 6A 0B 

這是模塊的“二進(jìn)制”表示。之所以用引號把“二進(jìn)制”引起來,是因?yàn)樯厦嫫鋵?shí)是用十六進(jìn)制表示的,不過把它變成二進(jìn)制或者人們能看懂的十進(jìn)制表示也很容易。

例如,下面是 num + 42 的各種表示方法。

5. 代碼是如何工作的:基于棧的虛擬機(jī)

如果你對具體的操作過程很好奇,那么這幅圖可以告訴你指令都做了什么。

從圖中我們可以注意到 加 操作并沒有指定哪兩個(gè)數(shù)字進(jìn)行加。這是因?yàn)?WebAssembly 是采用“基于棧的虛擬機(jī)”的機(jī)制。即一個(gè)操作符所需要的所有值,在操作進(jìn)行之前都已經(jīng)存放在堆棧中。

所有的操作符,比如加法,都知道自己需要多少個(gè)值。加需要兩個(gè)值,所以它從堆棧頂部取兩個(gè)值就可以了。那么加指令就可以變的更短(單字節(jié)),因?yàn)橹噶畈恍枰付ㄔ醇拇嫫骱湍康募拇嫫?。這也使得 .wasm 文件變得更小,進(jìn)而使得加載 .wasm 文件更快。

盡管 WebAssembly 使用基于棧的虛擬機(jī),但是并不是說在實(shí)際的物理機(jī)器上它就是這么生效的。當(dāng)瀏覽器翻譯 WebAssembly 到機(jī)器碼時(shí),瀏覽器會(huì)使用寄存器,而 WebAssembly 代碼并不指定用哪些寄存器,這樣做的好處是給瀏覽器***的自由度,讓其自己來進(jìn)行寄存器的***分配。

6. WebAssembly 模塊的組成部分

除了上面介紹的,.wasm 文件還有其他部分。一些組成部分對于模塊來講是必須的,一些是可選的。

必須部分:

  • Type。在模塊中定義的函數(shù)的函數(shù)聲明和所有引入函數(shù)的函數(shù)聲明。
  • Function。給出模塊中每個(gè)函數(shù)一個(gè)索引。
  • Code。模塊中每個(gè)函數(shù)的實(shí)際函數(shù)體。

可選部分:

  • Export。使函數(shù)、內(nèi)存、表(tables)、全局變量等對其他 WebAssembly 或 JavaScript 可見,允許動(dòng)態(tài)鏈接一些分開編譯的組件,即 .dll 的WebAssembly 版本。
  • Import。允許從其他 WebAssembly 或者 JavaScript 中導(dǎo)入指定的函數(shù)、內(nèi)存、表或者全局變量。
  • Start。當(dāng) WebAssembly 模塊加載進(jìn)來的時(shí)候,可以自動(dòng)運(yùn)行的函數(shù)(類似于 main 函數(shù))。
  • Global。聲明模塊的全局變量。
  • Memory。定義模塊用到的內(nèi)存。
  • Table。使得可以映射到 WebAssembly 模塊以外的值,如映射到 JavaScript 的對象。這在間接函數(shù)調(diào)用時(shí)很有用。
  • Data。初始化導(dǎo)入的或者局部內(nèi)存。
  • Element。初始化導(dǎo)入的或者局部的表。

如果你想了解關(guān)于這些組成部分的更深入的內(nèi)容,可以閱讀這些組成部分的工作原理。

二、為什么 WebAssembly 更快?

上面我介紹了如何編寫 WebAssembly 程序,也表達(dá)了我希望看到更多的開發(fā)者在自己的工程中同時(shí)使用 WebAssembly 和 JavaScript 的期許。

開發(fā)者們不必糾結(jié)于到底選擇 WebAssembly 還是 JavaScript,已經(jīng)有了 JavaScript 工程的開發(fā)者們,希望能把部分 JavaScript 替換成 WebAssembly 來嘗試使用。

例如,正在開發(fā) React 程序的團(tuán)隊(duì)可以把協(xié)調(diào)性代碼(即虛擬 DOM)替換成 WebAssembly 的版本。而對于你的 web 應(yīng)用的用戶來說,他們就跟以前一樣使用,不會(huì)發(fā)生任何變化,同時(shí)他們還能享受到 WebAssembly 所帶來的好處——快。

而開發(fā)者們選擇替換為 WebAssembly 的原因正是因?yàn)?WebAssembly 比較快。

1. 當(dāng)前的 JavaScript 性能如何?

在我們了解 JavaScript 和 WebAssembly 的性能區(qū)別之前,需要先理解 JS 引擎的工作原理。

下面這張圖片介紹了性能使用的大概分布情況。

JS 引擎在圖中各個(gè)部分所花的時(shí)間取決于頁面所用的 JavaScript 代碼。圖表中的比例并不代表真實(shí)情況下的確切比例情況。

JS 引擎

圖中的每一個(gè)顏色條都代表了不同的任務(wù):

  • Parsing——表示把源代碼變成解釋器可以運(yùn)行的代碼所花的時(shí)間;
  • Compiling + optimizing——表示基線編譯器和優(yōu)化編譯器花的時(shí)間。一些優(yōu)化編譯器的工作并不在主線程運(yùn)行,不包含在這里。
  • Re-optimizing——當(dāng) JIT 發(fā)現(xiàn)優(yōu)化假設(shè)錯(cuò)誤,丟棄優(yōu)化代碼所花的時(shí)間。包括重優(yōu)化的時(shí)間、拋棄并返回到基線編譯器的時(shí)間。
  • Execution——執(zhí)行代碼的時(shí)間
  • Garbage collection——垃圾回收,清理內(nèi)存的時(shí)間

這里注意:這些任務(wù)并不是離散執(zhí)行的,或者按固定順序依次執(zhí)行的。而是交叉執(zhí)行,比如正在進(jìn)行解析過程時(shí),其他一些代碼正在運(yùn)行,而另一些正在編譯。

這樣的交叉執(zhí)行給早期 JavaScript 帶來了很大的效率提升,早期的 JavaScript 執(zhí)行類似于下圖,各個(gè)過程順序進(jìn)行:

早期的 JavaScript 執(zhí)行類似于下圖

早期時(shí),JavaScript 只有解釋器,執(zhí)行起來非常慢。當(dāng)引入了 JIT 后,大大提升了執(zhí)行效率,縮短了執(zhí)行時(shí)間。

JIT 所付出的開銷是對代碼的監(jiān)視和編譯時(shí)間。JavaScript 開發(fā)者可以像以前那樣開發(fā) JavaScript 程序,而同樣的程序,解析和編譯的時(shí)間也大大縮短。這就使得開發(fā)者們更加傾向于開發(fā)更復(fù)雜的 JavaScript 應(yīng)用。

同時(shí),這也說明了執(zhí)行效率上還有很大的提升空間。

2. WebAssembly 對比

下面是 WebAssembly 和典型的 web 應(yīng)用的近似對比圖:

各種瀏覽器處理上圖中不同的過程,有著細(xì)微的差別,拿 SpiderMonkey 作為例子。

3. 文件獲取

這一步并沒有顯示在圖表中,但是這看似簡單地從服務(wù)器獲取文件這個(gè)步驟,卻會(huì)花費(fèi)很長時(shí)間。

WebAssembly 比 JavaScript 的壓縮率更高,所以文件獲取也更快。即便通過壓縮算法可以顯著地減小 JavaScript 的包大小,但是壓縮后的 WebAssembly 的二進(jìn)制代碼依然更小。

這就是說在服務(wù)器和客戶端之間傳輸文件更快,尤其在網(wǎng)絡(luò)不好的情況下。

4. 解析

當(dāng)?shù)竭_(dá)瀏覽器時(shí),JavaScript 源代碼就被解析成了抽象語法樹。

瀏覽器采用懶加載的方式進(jìn)行,只解析真正需要的部分,而對于瀏覽器暫時(shí)不需要的函數(shù)只保留它的樁(stub,譯者注:關(guān)于樁的解釋可以在之前的文章中有提及)。

解析過后 AST (抽象語法樹)就變成了中間代碼(叫做字節(jié)碼),提供給 JS 引擎編譯。

而 WebAssembly 則不需要這種轉(zhuǎn)換,因?yàn)樗旧砭褪侵虚g代碼。它要做的只是解碼并且檢查確認(rèn)代碼沒有錯(cuò)誤就可以了。

5. 編譯和優(yōu)化

在關(guān)于 JIT 的文章中,我有介紹過,JavaScript 是在代碼的執(zhí)行階段編譯的。因?yàn)樗侨躅愋驼Z言,當(dāng)變量類型發(fā)生變化時(shí),同樣的代碼會(huì)被編譯成不同版本。

不同瀏覽器處理 WebAssembly 的編譯過程也不同,有些瀏覽器只對 WebAssembly 做基線編譯,而另一些瀏覽器用 JIT 來編譯。

不論哪種方式,WebAssembly 都更貼近機(jī)器碼,所以它更快,使它更快的原因有幾個(gè):

在編譯優(yōu)化代碼之前,它不需要提前運(yùn)行代碼以知道變量都是什么類型。

編譯器不需要對同樣的代碼做不同版本的編譯。

很多優(yōu)化在 LLVM 階段就已經(jīng)做完了,所以在編譯和優(yōu)化的時(shí)候沒有太多的優(yōu)化需要做。

編譯和優(yōu)化

6. 重優(yōu)化

有些情況下,JIT 會(huì)反復(fù)地進(jìn)行“拋棄優(yōu)化代碼<->重優(yōu)化”過程。

當(dāng) JIT 在優(yōu)化假設(shè)階段做的假設(shè),執(zhí)行階段發(fā)現(xiàn)是不正確的時(shí)候,就會(huì)發(fā)生這種情況。比如當(dāng)循環(huán)中發(fā)現(xiàn)本次循環(huán)所使用的變量類型和上次循環(huán)的類型不一樣,或者原型鏈中插入了新的函數(shù),都會(huì)使 JIT 拋棄已優(yōu)化的代碼。

反優(yōu)化過程有兩部分開銷。***,需要花時(shí)間丟掉已優(yōu)化的代碼并且回到基線版本。第二,如果函數(shù)依舊頻繁被調(diào)用,JIT 可能會(huì)再次把它發(fā)送到優(yōu)化編譯器,又做一次優(yōu)化編譯,這是在做無用功。

在 WebAssembly 中,類型都是確定了的,所以 JIT 不需要根據(jù)變量的類型做優(yōu)化假設(shè)。也就是說 WebAssembly 沒有重優(yōu)化階段。

重優(yōu)化

7. 執(zhí)行

自己也可以寫出執(zhí)行效率很高的 JavaScript 代碼。你需要了解 JIT 的優(yōu)化機(jī)制,例如你要知道什么樣的代碼編譯器會(huì)對其進(jìn)行特殊處理(JIT 文章里面有提到過)。

然而大多數(shù)的開發(fā)者是不知道 JIT 內(nèi)部的實(shí)現(xiàn)機(jī)制的。即使開發(fā)者知道 JIT 的內(nèi)部機(jī)制,也很難寫出符合 JIT 標(biāo)準(zhǔn)的代碼,因?yàn)槿藗兺ǔ榱舜a可讀性更好而使用的編碼模式,恰恰不合適編譯器對代碼的優(yōu)化。

加之 JIT 會(huì)針對不同的瀏覽器做不同的優(yōu)化,所以對于一個(gè)瀏覽器優(yōu)化的比較好,很可能在另外一個(gè)瀏覽器上執(zhí)行效率就比較差。

正是因?yàn)檫@樣,執(zhí)行 WebAssembly 通常會(huì)比較快,很多 JIT 為 JavaScript 所做的優(yōu)化在 WebAssembly 并不需要。另外,WebAssembly 就是為了編譯器而設(shè)計(jì)的,開發(fā)人員不直接對其進(jìn)行編程,這樣就使得 WebAssembly 專注于提供更加理想的指令(執(zhí)行效率更高的指令)給機(jī)器就好了。

執(zhí)行效率方面,不同的代碼功能有不同的效果,一般來講執(zhí)行效率會(huì)提高 10% - 800%。

執(zhí)行

8. 垃圾回收

JavaScript 中,開發(fā)者不需要手動(dòng)清理內(nèi)存中不用的變量。JS 引擎會(huì)自動(dòng)地做這件事情,這個(gè)過程叫做垃圾回收。

可是,當(dāng)你想要實(shí)現(xiàn)性能可控,垃圾回收可能就是個(gè)問題了。垃圾回收器會(huì)自動(dòng)開始,這是不受你控制的,所以很有可能它會(huì)在一個(gè)不合適的時(shí)機(jī)啟動(dòng)。目前的大多數(shù)瀏覽器已經(jīng)能給垃圾回收安排一個(gè)合理的啟動(dòng)時(shí)間,不過這還是會(huì)增加代碼執(zhí)行的開銷。

目前為止,WebAssembly 不支持垃圾回收。內(nèi)存操作都是手動(dòng)控制的(像 C、C++一樣)。這對于開發(fā)者來講確實(shí)增加了些開發(fā)成本,不過這也使代碼的執(zhí)行效率更高。

WebAssembly 不支持垃圾回收

9. 總結(jié)

WebAssembly 比 JavaScript 執(zhí)行更快是因?yàn)椋?/p>

  • 文件抓取階段,WebAssembly 比 JavaScript 抓取文件更快。即使 JavaScript 進(jìn)行了壓縮,WebAssembly 文件的體積也比 JavaScript 更小;
  • 解析階段,WebAssembly 的解碼時(shí)間比 JavaScript 的解析時(shí)間更短;
  • 編譯和優(yōu)化階段,WebAssembly 更具優(yōu)勢,因?yàn)?WebAssembly 的代碼更接近機(jī)器碼,而 JavaScript 要先通過服務(wù)器端進(jìn)行代碼優(yōu)化。
  • 重優(yōu)化階段,WebAssembly 不會(huì)發(fā)生重優(yōu)化現(xiàn)象。而 JS 引擎的優(yōu)化假設(shè)則可能會(huì)發(fā)生“拋棄優(yōu)化代碼<->重優(yōu)化”現(xiàn)象。
  • 執(zhí)行階段,WebAssembly 更快是因?yàn)殚_發(fā)人員不需要懂太多的編譯器技巧,而這在 JavaScript 中是需要的。WebAssembly 代碼也更適合生成機(jī)器執(zhí)行效率更高的指令。
  • 垃圾回收階段,WebAssembly 垃圾回收都是手動(dòng)控制的,效率比自動(dòng)回收更高。

這就是為什么在大多數(shù)情況下,同一個(gè)任務(wù) WebAssembly 比 JavaScript 表現(xiàn)更好的原因。

但是,還有一些情況 WebAssembly 表現(xiàn)的會(huì)不如預(yù)期;同時(shí) WebAssembly 的未來也會(huì)朝著使 WebAssembly 執(zhí)行效率更高的方向發(fā)展。這些我會(huì)在下一篇文章《WebAssembly 的現(xiàn)在與未來》中介紹。

點(diǎn)擊《WebAssembly 系列(四)WebAssembly 工作原理》《WebAssembly 系列(五)為什么 WebAssembly 更快?》閱讀原文。

【本文是51CTO專欄作者“胡子大哈”的原創(chuàng)文章,轉(zhuǎn)載請聯(lián)系作者本人獲取授權(quán)】

戳這里,看該作者更多好文

責(zé)任編輯:趙寧寧 來源: 51CTO專欄
相關(guān)推薦

2012-04-20 13:27:17

NFC

2017-03-19 22:43:12

WebAssemblyJavaScript編程

2024-04-16 00:13:52

JS網(wǎng)絡(luò)狀態(tài)ts類

2022-08-15 06:00:00

二進(jìn)制編程語言

2023-05-05 17:20:04

2023-03-27 13:25:18

WebAssembl語言Scheme

2021-06-11 09:00:00

語言WebWebAssembly

2022-05-16 10:25:03

Web內(nèi)部垃圾收集安全性

2020-11-03 08:12:20

WebAssemblyAPI

2023-01-31 09:02:24

JSVMVR

2022-06-22 10:04:29

JavaScriptRust語言

2022-01-16 20:25:57

WebAssembly網(wǎng)絡(luò)

2018-10-15 17:31:00

網(wǎng)絡(luò)安全病毒網(wǎng)絡(luò)攻擊

2022-06-02 08:01:11

云原生工具

2022-10-28 16:57:18

DockerWasm

2023-12-10 16:48:00

Wasm瀏覽器

2018-07-30 13:29:04

WebAssemblyGo語言

2017-03-19 20:41:57

WebAssemblyJavaScript編程

2011-08-22 16:39:15

iOS內(nèi)存

2021-08-30 08:00:00

編程語言WebAssembly安全
點(diǎn)贊
收藏

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