如果提及近年來讓人最為興奮的新技術(shù),非WebAssembly 莫屬。作為一種低級的類匯編語言,WebAssembly以緊湊二進(jìn)制的格式存儲,為C/C++, Rust等擁有低級內(nèi)存的模型語言提供了新的編譯目標(biāo)。正因如此,WebAssembly體積更小,可以以接近原生性能的速度運(yùn)行。 WebAssembly 技術(shù)本身具有非常多的優(yōu)點(diǎn),雖始于瀏覽器但已經(jīng)開始不斷地被各個(gè)語言及平臺所集成,在實(shí)際的工業(yè)化落地中,區(qū)塊鏈、邊緣計(jì)算、游戲及圖像視頻等多個(gè)領(lǐng)域都依靠 WebAssembly 創(chuàng)造出了讓人稱贊的產(chǎn)品。 WebAssembly的應(yīng)用場景
WebAssembly的主要特性
WebAssembly VS Javascript既然提到了Web技術(shù),就不得不提另一款在Web項(xiàng)目開發(fā)中大放異彩的腳本語言Javascript。1995 年,Brendan Eich 用了不到 10 天就創(chuàng)建了 Javascript,其最初主要應(yīng)用于表單驗(yàn)證,而非以速度見長。隨著各類應(yīng)用功能的復(fù)雜化,受限于 JavaScript 語言本身動態(tài)類型和解釋執(zhí)行的設(shè)計(jì),其性能問題逐漸凸現(xiàn)。 2008年,圍繞著瀏覽器性能開展的大戰(zhàn)終于在各大瀏覽器廠商間爆發(fā),在先后經(jīng)歷了即時(shí)編譯器(JITs),以及用Node.js和Electron構(gòu)建應(yīng)用程序的時(shí)期后,WebAssembly有望成為JS引擎突破下一性能瓶頸的轉(zhuǎn)折點(diǎn)。 為此,這兩者經(jīng)常被用于比較,甚至一度出現(xiàn)WebAssembly 終將替代 Javascript的言論。的確,作為類匯編語言,WebAssembly解決了Javascript最常為人詬病的性能問題,也正是基于此,WebAssembly注定不適合開發(fā)人員手寫代碼,只能為其他語言提供一個(gè)編譯目標(biāo)。 因此,這兩種技術(shù)的關(guān)系不是競爭,反而更像是合作共贏。通過 Javascript API,你可以將 WebAssembly 模塊加載到你的頁面中。也就是說,你可以通過 WebAssembly 來充分利用編譯代碼的性能,同時(shí)保持 Javascript 的靈活性。 二者性能對比下圖為我們展現(xiàn)了JS引擎運(yùn)行程序和運(yùn)行Wasm的耗時(shí)對比: JS引擎運(yùn)行程序時(shí),需要經(jīng)歷源碼轉(zhuǎn)換(parse)、生成字節(jié)碼(compile + optimize)、編譯器優(yōu)化(re-optimize)、代碼執(zhí)行(execute)和內(nèi)存清理(GC)這五個(gè)階段:
大部分情況下,JS在執(zhí)行階段將字節(jié)碼編譯成機(jī)器碼,這一階段十分耗時(shí)。(這是由于JS的動態(tài)性所導(dǎo)致,相同的代碼會被不同的類型重新編譯)。而Wasm不需要被解析,也不需要在運(yùn)行時(shí)動態(tài)檢測數(shù)據(jù)類型,由于它已經(jīng)是字節(jié)碼了,所以只需要簡單解碼,即可包含所有的類型信息。 正是因?yàn)閃asm的大部分優(yōu)化工作已經(jīng)在LLVM的前端部分完成了,所以編譯優(yōu)化的工作很少,這便是其高性能的主要體現(xiàn)。 編譯模型(LLVM)LLVM(Low-Level-Virtural-Machine), 底層虛擬機(jī)架構(gòu),優(yōu)點(diǎn)包括:
WebAssembly 與LLVM結(jié)合WebAssembly與LLVM結(jié)合,不需要為各個(gè)語言額外添加前端編譯工具,中間的IL可以不斷地優(yōu)化,僅需添加一個(gè)'后端',就可以讓大部分語言編譯成wasm。這個(gè)'后端'不同于之前提到的后端,它不會直接生成機(jī)器碼,它生成的wasm,會由瀏覽器wasm運(yùn)行時(shí)負(fù)責(zé)編譯運(yùn)行。 這就是WebAssembly的編譯原理, 既然WebAssembly的核心目標(biāo)是與Javascript等Web技術(shù)兼容, 那么其兼容到底程度如何?下面,我們將通過項(xiàng)目實(shí)戰(zhàn)來驗(yàn)證。 注:具體的代碼和Demo示例將在grapecity的公開課中進(jìn)行演示,歡迎各位同學(xué)點(diǎn)擊文末“了解更多”觀看。 項(xiàng)目實(shí)戰(zhàn):WebAssembly + Javascript在進(jìn)入項(xiàng)目實(shí)戰(zhàn)之前,大家需要理解一個(gè)核心概念,即JavaScript為何能完全控制WebAssembly代碼,并執(zhí)行下載和編譯運(yùn)行:
可見,JavaScript API為開發(fā)者提供了創(chuàng)建模塊、內(nèi)存、表格和實(shí)例的能力。 通過一個(gè)WebAssembly實(shí)例,JavaScript能夠調(diào)用該實(shí)例暴露的函數(shù),把JavaScript函數(shù)導(dǎo)入到WebAssembly實(shí)例中,WebAssembly也能調(diào)用JavaScript函數(shù)。 另外,WebAssembly不能直接讀寫DOM,只能調(diào)用JavaScript,并且只能傳入整形和浮點(diǎn)型的原始數(shù)據(jù)作為參數(shù)。因此,JavaScript能夠完全控制WebAssembly代碼實(shí)現(xiàn)下載、編譯、運(yùn)行, JavaScript開發(fā)者也可以把WebAssembly想象成一個(gè)生成高性能函數(shù)的JavaScript特性。 代碼示例wasm(Rust): wasm_bindgen主要用來生成一些膠水代碼,簡化開發(fā)者在JS和wasm之間的方法調(diào)用。 JS: 項(xiàng)目結(jié)構(gòu)IDEVSCode+插件Rust 執(zhí)行步驟
結(jié)語通過簡單介紹 WebAssembly 的應(yīng)用場景和主要特性,我們能更好地夠理解 WebAssembly 技術(shù)的演變過程。如果您想更詳細(xì)的學(xué)習(xí)相關(guān)內(nèi)容,可以點(diǎn)擊下方“了解更多”觀看視頻進(jìn)行學(xué)習(xí)。 |
|