<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          為什么WebAssembly不是JavaScript的終結(jié)者,而是它的“助推器”?

          共 5174字,需瀏覽 11分鐘

           ·

          2021-09-17 17:33


          導(dǎo)語 | 自從JavaScript創(chuàng)建到現(xiàn)在,每10年都會有新的變化,下一個10年的爆點在哪,可能就是WebAssembly!但WebAssembly絕不是JavaScript的終結(jié)者,反而是它的“助推器”!這是為什么呢?接下來我將帶你揭曉答案,讓你10分鐘快速掌握WebAssembly!



          一、了解WebAssembly


          (一)什么是WebAssembly?


          官網(wǎng)定義:WebAssembly/wasm WebAssembly或者wasm是一個可移植、體積小、加載快并且兼容Web的全新格式(二進制),是由主流瀏覽器廠商組成的W3C社區(qū)團體制定的一個新的規(guī)范。



          (二)發(fā)展歷史



          1995年,大神布蘭登·艾奇(Brendan Eich),僅僅花了10天就將偉大的JavaScript擼出來了,引起了轟動。但是Js的設(shè)計初衷是想設(shè)計出一個面向非專業(yè)編程人員和網(wǎng)頁設(shè)計師的解釋型語言。由于時間太短,細節(jié)考慮的不夠周全,導(dǎo)致留下很多坑,所以后來很長一段時間,JavaScript的執(zhí)行速度一直備受詬病。


          2008年,瀏覽器的性能大戰(zhàn)打響,眾多瀏覽器引入了即時(JIT)編譯使得JavaScript運行速度快了一個量級。但是對于JavaScript這種弱數(shù)據(jù)類型的語言來說,要實現(xiàn)一個完美的JIT非常難。因為Javascript是一個沒有類型的語言,而且像+這樣的符號又能夠重載,譬如這樣的代碼:


          const sum = (a, b, c) => a + b + c;


          這是一個求和函數(shù),可以直接放在瀏覽器的控制臺下運行,如果傳參都是整數(shù)時,結(jié)果是整數(shù)相加的結(jié)果:如console.log(sum(1, 2, 3)),答案是6。但是,如果至少有一個是字符串,則結(jié)果是按照字符串拼接出的結(jié)果,如console.log(sum('1', 2, 3)),答案是“123”。也就是說,JIT在遇到第一個sum時會編譯成整數(shù)相加的機器碼;但是在碰到第二個sum調(diào)用時,不得不重新編譯一遍。這樣一來,JIT帶來的效率提升便被抵消了。


          隨著JS達到了性能天花板,在當前復(fù)雜運算及游戲面前已完全力不從心。無法滿足一些大型web項目開發(fā),于是三大瀏覽器巨頭分別提出了自己的解決方案:



          我們熟知的四大主流瀏覽器廠商Google Chrome、Apple Safari、Microsoft Edge和Mozilla FireFox,覺得Mozilla FireFox所推出的asm.js很有前景,為了讓大家都能使用,于是他們就共同參與開發(fā),基于asm.js制定一個標準,也就是WebAssembly。



          2015年,WebAssembly首次發(fā)布,并可直接在瀏覽器中運行。


          2017年3月份,四大廠商均宣布已經(jīng)于最新版本的瀏覽器中支持了WebAssembly的初始版本,這意味著WebAssembly技術(shù)已經(jīng)實際落地。


          2019年,被正式加入Web的標準大家庭中。



          (三)WebAssembly影響


          大幅度提高Javascript的性能,同時也不損失安全性。Webapp和原生App的性能差距變得很小。


          基本之前需要插件來提高速度的技術(shù)已經(jīng)沒有必要了,網(wǎng)頁應(yīng)用的移植性會變得更好。


          WebAssembly可以允許任何語言編譯到它制定的AST tree,相當于使用其他高級語言寫的代碼可以直接在網(wǎng)頁上運行。



          (四)工作原理



          WebAssembly的工作原理簡要來說是將C,C++, Rust等靜態(tài)語言通過編譯器的程序編譯成瀏覽器能夠運行的wasm二進制文件,當瀏覽器加載wasm文件后編譯為本地機器碼后運行。


          為什么能提升當前js的性能?


          正常的JS:在瀏覽器中,對JavaScript源碼進行解析,生成抽象語法樹或者字節(jié)碼(parse),JIT編譯器會對生成的代碼進行編譯優(yōu)化,當然后當發(fā)生去優(yōu)化時,再去重新編譯優(yōu)化,最后執(zhí)行。


          WebAssembly:則省去了比較耗時的解析和編譯的過程,是直接生成的二進制可執(zhí)行機器碼進行執(zhí)行。



          (五)瀏覽器支持



          由圖可見,無論是PC、移動端還是服務(wù)器,都已經(jīng)開始支持WebAssembly了,這也說明WebAssembly已經(jīng)開始普及。


          二、實戰(zhàn)演練


          (一)語言選擇


          實戰(zhàn)開始:首先確認你選擇開發(fā)的語言:


          • 當你在用C/C++之類的語言編寫模塊時,你可以使用Emscripten來將它編譯到WebAssembly。


          • 當你使用Rust語言編寫模塊時,需要一個額外工具wasm-pack。它會把代碼編譯成WebAssembly并制造出正確的npm包。


          • 當你使用Java語言來編寫模塊時,據(jù)說TeaVM可以將JVM字節(jié)碼翻譯成JavaScript,還能翻譯成WebAssembly,現(xiàn)在還不成熟。


          • 當你使用php語言來編寫模塊時,php2wasm可以接把PHP代碼編譯成wasm,現(xiàn)在還不成熟。


          • 如果你還想保持js的編寫風格,那就用typescript來編寫吧,用assemblyscript來生成wasm。


          確認好你要選擇的語言語種,應(yīng)該總有一款適合你的!


          如果還不夠,請移位:

          https://github.com/appcypher/awesome-wasm-langs



          (二)環(huán)境準備


          根據(jù)官網(wǎng)的引導(dǎo),使用C/C++來編寫部分代碼,并在瀏覽器中運行,以下均是在MacOS環(huán)境下進行的操作。


          首先搭建Emscripten


          • 沒有升級過python環(huán)境的同學,電腦會有個默認的版本python2.7.x,此時需要到phthon官網(wǎng)下載最新的python版本進行安裝。

          • 在應(yīng)用程序中,雙擊“install Certificates.command”,否則會出現(xiàn)證書驗證異常,導(dǎo)致無法后續(xù)步驟。



          #通過一個 git 克隆獲取 emscriptengit clone https://github.com/juj/emsdk.git
          #下載,安裝并激活 sdk,這個步驟可能需要一點時間cd emsdk./emsdk install latest./emsdk activate latest
          #讓環(huán)境生效source ./emsdk_env.sh
          #確認安裝的內(nèi)容可以正常運行emcc --version



          OK,可以進行代碼編寫了!



          (三)樣例編寫


          • 用C語言編寫的斐波那契數(shù)列(遞歸)


          #include <stdio.h>
          int fib(int n) { return n <= 1 ? 1 : fib(n - 1) + fib(n - 2);}


          • 編譯生成wasm


          emcc fib.c -O3 -s WASM=1 -s SIDE_MODULE=1 -s EXPORTED_FUNCTIONS='["_fib"]' -o fib.wasm


          (注:emcc就是Emscripten編譯器指令,fib.c是輸入文件,-s SIDE_MODULE=1表示這就是一個模塊,-s EXPORTED_FUNCTIONS表示導(dǎo)出的接口函數(shù),-o fib.wasm`是輸出的文件,更多的命令字可參考官網(wǎng))


          通過以上命令可生成名字為fib的wasm文件,可在js中進行引用,并且調(diào)用。


          • 如何加載wasm


          直接引用到頁面中,官網(wǎng)是推薦兩種,一個是fetch,一個是XMLHttpRequest,本文以fetch為例,在html頁面中引入上面的文件,如下:


          fetch('你引入wasm路徑').then(res => {return res.arrayBuffer()})  //引入到內(nèi)存中,使其在array buffer中可用.then(WebAssembly.instantiate)  //編譯和實例化 WebAssembly 代碼.then(module => {   //寫你引用此模塊的目的})


          將fib.c生成的fib.wasm后,在html中引用如下:


          fetch('./wasm/fib.wasm').then(res => {return res.arrayBuffer()}).then(WebAssembly.instantiate) .then(module => {   // console.log(module.instance.exports.fib(value))  let res = module.instance.exports.fib(value);  $("#result").text(res);  let endtime = new Date().getTime();  $("#period").text(endtime - starttime);})


          以上,環(huán)境和相關(guān)demo已經(jīng)寫好了,下面來看一下WebAssembly的執(zhí)行性能。



          (四)性能比較


          在demo頁面中同樣用js寫了一個遞歸的方法,和同時引用fib.wasm,做了以下性能比較:



          為了減少誤差性,在代碼中分別用js和wasm做定時請求N次,來看他們的耗時,如下圖所示:



          可以看到,同樣是計算40的遞歸算法,js時間基本上都是在1270ms左右,而編譯生成的wasm基本上都在680ms左右,也就是說在處理40的遞歸下,性能提升至原來的1.87倍。


          同時,為了進行性能上的對比,對遞歸數(shù)做了不同的取值,來看請求結(jié)果及耗時,如下圖所示:



          可以看到,遞歸數(shù)越大,也就是運算層次越多,webassembly相比于JS的優(yōu)勢就越明顯,也就是在比較復(fù)雜的JS運算或者處理中,用webassembly會更合適。



          三、如何與JS互通


          交互離不開相互調(diào)用,在瀏覽器中,了解到了在js中如何調(diào)用WebAssembly中的接口,那在WebAssembly中如何引用js相關(guān)函數(shù)呢?下面簡單和您介紹下。


          (一)方法調(diào)用


          Emscripten提供兩種方法讓C/C++調(diào)用JavaScript:


          • 使用emscripten_run_script()運行js腳本,一種是寫“內(nèi)聯(lián)JavaScript”。


          emscripten_run_script("alert('hi')");


          • 用EM_ASM()和其他相關(guān)宏寫內(nèi)聯(lián)JavaScript,稍快,這個是推薦的寫法。


          #include <emscripten.h>
          int main() { EM_ASM( alert('hello world!'); throw 'all done'; ); return 0;}



          (二)示例demo


          #include 

          命令行,生成可執(zhí)行的html文件:


          emcc test.c -s WASM=1 -o test.html


          運行結(jié)果:



          可以看到,無論是哪種引用方式,都可以運行出你想要的結(jié)果。



          四、總結(jié)


          一句話體積小,速度快,二進制文件,執(zhí)行效率高。


          適用場景在瀏覽器中使用視頻、游戲、AR、AI等比較合適使用WebAssembly,如果將服務(wù)器上的加密,想要放在web端用這個實現(xiàn)也可以。


          市場現(xiàn)狀flv.js用WebAssembly重寫后性能有很大提升;AutoCAD,Google Earth,用WebAssembly都開始支持了web版本等等。


          突破很多靜態(tài)語言轉(zhuǎn)成wasm的生態(tài)工具還不完善不成熟,都還處于起步階段;另外學習資料太少,還需要更多的人去探索去踩坑。


          另希望有對WebAssembly感興趣的同學,可以一起交流探討。


          參考鏈接:

          1.https://developer.ibm.com/zh/technologies/web-development/articles/wa-lo-webassembly-status-and-reality/

          2.https://zhuanlan.zhihu.com/p/49464798

          3.https://blog.csdn.net/liubiggun/article/details/79848948



           作者簡介


          任春燕(helenren)

          騰訊高級運營開發(fā)工程師

          騰訊高級運營開發(fā)工程師,目前從事前端開發(fā)相關(guān)工作,有豐富的Web前端,大前端,小游戲等開發(fā)經(jīng)驗。



           推薦閱讀


          快人一步掌握vue源碼解讀,搞定diff算法!(超詳細)

          事務(wù)消息大揭秘!RocketMQ、Kafka、Pulsar全方位對比

          Linux入門必看:如何在60秒內(nèi)分析Linux性能?

          “Docker VS Kubernetes”是共生還是相愛相殺?





          瀏覽 52
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产精品美女久久 | 北条麻妃无码在线 | 欧美三级韩国三级日本三斤在线观看 | 韩国一区二区三区四区不卡视频 | 久热这里只有精品89 |