国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

WebAssembly起步

shiina / 2152人閱讀

摘要:解析下載后,需要引擎經過兩個階段轉換成,然后再轉換為瀏覽器需要的中間字節(jié)碼。未來所有支持編譯到字節(jié)碼的編程語言,理論上都可以輸出。

了解WebAssembly原理

WebAssembly是一種可以在瀏覽器上運行的二進制可執(zhí)行格式文件。它將成為瀏覽器進化史上又一次革命。

自從瀏覽器問世以來,javascript就成為瀏覽器上執(zhí)行程序的唯一標準,越來越多的應用程序通過javascript開發(fā),并運行于瀏覽器上;而隨著瀏覽器上h5程序功能的豐富,也對瀏覽器提出了更多的挑戰(zhàn)。其中一條最為重要的就是性能問題。javascript是一種弱類型,解釋性的腳本語言。它天生運行速度慢,成為了很多h5應用的軟肋。雖然2008年google V8引入了即時編譯等技術使js的運行速度提升了一大截,但是一些大型應用程序,比如游戲,視頻編輯,壓縮,算法等依然不適合運行在瀏覽器上。

WebAssembly的到來解決了這個問題,并給開發(fā)基于瀏覽器的應用程序提供了另外的編程語言選擇。2017年三大瀏覽器同時增加了WebAssembly支持,標志著WebAssembly已經達到生產實用標準。

為什么WebAssembly比javascript快

回答這個問題需要洞悉瀏覽器執(zhí)行javascript代碼的各個環(huán)節(jié)。
瀏覽器加載并執(zhí)行javascript大概可分為如下幾個環(huán)節(jié): 下載,解析,執(zhí)行和優(yōu)化,垃圾回收。

下載

javascript是以純文本格式下載的。相比,webassembly使用二進制格式存儲,結構更精簡,更小。

解析

javascript下載后,需要js引擎經過tokenize, parse兩個階段轉換成AST(abstract syntax tree),然后再轉換為瀏覽器需要的中間字節(jié)碼。由于js是比較高級的語言,解析js也相對要做更多的事情。webassembly的格式類似于匯編語言,本來就是中間字節(jié)碼,和需要運行的機器碼更相近,需要簡單的轉換工作即可轉化為CPU可以直接執(zhí)行的機器碼。

下圖是一個真實運行的webassembly(它是文本的,只是為了方便調試),可以看出它和匯編是很相似的,更易轉化為機器碼。

執(zhí)行和優(yōu)化

在執(zhí)行階段,js普遍采用解釋執(zhí)行策略,相當于每一次執(zhí)行javascript指令都要通過js引擎中轉給cpu。現代的js引擎同時采用了即時編譯的策略。這需要同時運行一個profiler,關注每個函數的調用情況。當profiler發(fā)現一個函數調用的比較多的時候,會把這個函數拋給編譯器,為它生成一個更快的編譯版本。某些情況下,參數類型會發(fā)生變化。這時,需要刪除之前的編譯版本,對新參數類型編譯新的版本。而webassembly由于類匯編的結構,只需簡單的編譯即可轉換為可直接運行在cpu上的機器碼,執(zhí)行更快。

垃圾回收

javascript運行期間需要同時間歇的運行一個垃圾回收器,掃描堆上的垃圾、釋放內存。垃圾回收器的運行又和js引擎的執(zhí)行是互斥的,導致js執(zhí)行間歇性的被垃圾回收器打斷。webassembly不負責垃圾回收,只能編程語言自行解決。于是不同的編程語言又有所不同。C/C++是手動管理內存(malloc/free, new/delete),rust則是基于生命周期的自動內存管理。所有這些內存管理方法都不需要間歇的全局暫停。因此性能更好。

從以上各個角度看WebAssembly確實比javascript性能高。事實上,目前階段WebAssembly執(zhí)行時間大概等于原生程序執(zhí)行時間X1.2。

WebAssembly的加載與執(zhí)行

wasm是WebAssembly格式的瀏覽器可執(zhí)行文件。它是二進制的,但是它并不像桌面win32程序一樣,可以隨便使用系統(tǒng)資源,調用操作系統(tǒng)api。事實上,所有與外界相關的操作都必須由javascript傳入。比如:要申請一段內存,必須由javascript申請了并傳給他。 瀏覽器上,javascript做不到的,它也做不到;javascript能做到的,它能做的更快。 這個就是它的價值。

目前必須要js啟動WebAssembly的加載和實例化(后面可能會有多帶帶的加載機制)。

如下函數,使用fetchAPI加載wasm文件,并實例化wasm模塊。

function fetchAndInstantiate(url, importObject) {
  return fetch(url).then(response =>
    response.arrayBuffer()
  ).then(bytes =>
    WebAssembly.instantiate(bytes, importObject)
  ).then(results =>
    results.instance
  );
}

fetchAndInstantiate("module.wasm", importObject).then(function(instance) {
  ...
})

importObject即瀏覽器需要向webassembly注入的交互api。

如下,是一個真實運行的importObject包括很多js函數。

注意global.memory就是webassembly程序執(zhí)行用到的內存,是js申請的一個大的ArrayBuffer。

學會WebAssembly開發(fā)

講了這么多WebAssembly的優(yōu)點,接下就講下WebAssembly的開發(fā)。

開發(fā)WebAssembly并不意味著需要手寫WebAssembly匯編程序。一個開源項目emscripten已經提供了sdk可以編譯C/C++,并輸出WebAssembly的wasm文件。目前,rust也已經支持編譯到wasm。未來所有支持編譯到LLVM字節(jié)碼的編程語言,理論上都可以輸出wasm。

安裝emscripten

下載emscripten sdk后,是個壓縮文件,其實是sdk包管理器。
需要執(zhí)行如下命令,完成sdk的安裝。

./emsdk update
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh

現在已經有個可用的emcc編譯器了,輸入:

emcc --version

查看編譯器版本。

emsdk安裝后, emscripten文件內是按版本號安裝的sdk內容,里面有很多C/C++用例,可以自行研究下。

簡單demo

這個簡單的C程序可以直接編譯為wasm。

#include 

int main() {
  printf("hello, world!
");
  return 0;
}
./emcc hello_world.c
node a.out.js

默認情況下,emcc只輸出了一個js(asmjs)。asmjs是webassembly的一個早期原型,可提供webassembly在舊版本瀏覽器上的兼容。按如下命令輸出webassembly二進制wasm。

./emcc hello_world.c -s WASM=1 -o index.html

這次編譯輸出了index.html, index.js, index.wasm三個文件。通過一個靜態(tài)服務器打開index.html,可以看到console里的輸出。

這個index.html是一個調試頁面。生產上加載webassembly一般都需要自己寫index.html,只保留js和wasm文件就夠了。

以上的例子中,printf的標準輸出被定向到了瀏覽器的console里面。 系統(tǒng)API調用被換成了js實現。 事實上很多l(xiāng)ibc里面的函數被emscripten實現成了瀏覽器上的兼容方案,從而更好的和瀏覽器結合。

環(huán)境

所有編程語言都要和它的運行環(huán)境打交道,否則除了把cpu跑滿,沒什么實用價值。跑在瀏覽器上的webassembly則是通過和js相互調用發(fā)揮它的作用。

Emscripten sdk提供了很多API與js運行環(huán)境/瀏覽器交互。定義在其中兩個頭文件中:

emscripten.h: 中定義了一些基礎功能相關API,包括調用js,文件讀寫,網絡請求等,這些API在node中也可以用。

html5.h中定義了瀏覽器中與DOM相關的各種操作,包括DOM,事件,設備相關等。

下面,抽出一些關鍵的API講下webassembly是如何與瀏覽器協(xié)同工作的。

調用js

EM_ASM宏,讓webassembly可以直接調用js。

EM_ASM(alert("hai"); alert("bai"));

如果需要從js獲取執(zhí)行結果,可以用EM_ASM_INTEM_ASM_DOUBLE兩個版本分別獲取intdouble類型的數值。

int x = EM_ASM_INT({
  return $0 + 42;
}, 100);

如果需要傳遞字符串給js,可以傳遞一個字符串起始的指針給js。由于js可以訪問整個wasm程序的內存區(qū)域,js用這個指針就可以從內存讀出字符串。Module對象上的UTF8ToString(ptr), UTF16ToString(ptr), UTF32ToString(ptr), Pointer_stringify(ptr, length)這幾個函數可獲得指針處的字符串。

char* sample = "This is a string";
  EM_ASM_({
      console.log("js got string:", Module.UTF8ToString($0));
  }, sample);
標準輸入輸出

標準輸出我們之前看過,printf最終被轉到Module.print,默認是console.log實現。
標準錯誤輸出最終會被轉到Module.printErr,默認是console.error實現。
對標準輸入的讀取在瀏覽器上變成了一個prompt框。體驗不好,盡量不要讀。

顯示

Emscripten支持兩種GUI展示方法。

DOM: wasm是可以調用js的,而js又可以操作DOM。因此,wasm可以通過js操作DOM,創(chuàng)建程序的GUI。

Webgl Canvas: 除了DOM,emscripten還可以提供了opengl es的瀏覽器實現。通過操作一個Webgl Canvas,把顯示內容畫在Canvas上。

事件循環(huán)

C++ GUI程序一般都有個事件循環(huán),其實就是個死循環(huán),反復獲取并處理GUI層面上的各種事件。這樣程序不會跑完main函數直接退出。webassembly程序跑在瀏覽器上,而瀏覽器本來就是事件驅動,已經有了一個事件循環(huán)。假如不改動直接上瀏覽器,就會卡死瀏覽器的GUI進程。因此webassembly程序需要由瀏覽器控制事件循環(huán)。

emscripten_set_main_loop(em_callback_func func, int fps, int simulate_infinite_loop)函數接受一個函數的指針后,瀏覽器會根據fps按時調用傳入的函數。

#include 
#include 

int frame = 0;
void main_loop(void) {
  printf("frame: %d
", frame);
  frame++;
}

int main(void) {
  emscripten_set_main_loop(main_loop, 0, 1);
  return 0;
}
存儲

瀏覽器隔離了程序直接操作存儲的權限,因而webapp是安全的,但很多C代碼都有同步操作文件的API,如open, write, close。為了兼容,emscripten實現了一個內存文件系統(tǒng),可以通過全局對象FS訪問。

下圖,是FS對象下的函數。

另外,emcc還提供了--preload-file參數,在webassembly程序加載的過程中,預加載文件放到虛擬文件系統(tǒng)中。

wasm中的文件雖然是內存的,但是支持通過indexDB持久化。
如下js,mount一個indexdb的文件夾到/data目錄,然后FS.syncfs把indexdb中的文件同步到內存。

FS.mkdir("/data");
FS.mount(IDBFS, {}, "/data");
FS.syncfs(true, function (err) {
});

接下來,所有,/data目錄下的讀寫,都在內存中的同步讀寫。當程序關閉的時候,需要調用FS.syncfs(false, function(err){})把內存中的文件反方向同步回indexdb。

emsdk提供了一些常用的C++庫的webassembly兼容版本。用emcc --show-ports命令顯示。如果要用SDL2,需要給emcc加入選項-s USE_SDL=2,鏈接SDL2庫。

目前,emcc內置支持這些庫。

$ emcc --show-ports
Available ports:
    zlib (USE_ZLIB=1; zlib license)
    libpng (USE_LIBPNG=1; zlib license)
    SDL2 (USE_SDL=2; zlib license)
    SDL2_image (USE_SDL_IMAGE=2; zlib license)
    ogg (USE_OGG=1; zlib license)
    vorbis (USE_VORBIS=1; zlib license)
    bullet (USE_BULLET=1; zlib license)
    freetype (USE_FREETYPE=1; freetype license)
    SDL2_ttf (USE_SDL_TTF=2; zlib license)
    SDL2_net (zlib license)
    Binaryen (Apache 2.0 license)
    cocos2d

如果所需要的庫沒在列表里,需要先用emsdk編譯所需要的庫(可能涉及到庫的改動)。再編譯并鏈接,輸出最終目標。emcc不支持動態(tài)鏈接。

展望

目前,webassembly已經完成MVP最小功能版本開發(fā),有非常注目的性能。可以遇見,未來將有更多h5 app/游戲通過webassembly獲得更好的體驗。使用C/C++/rust進行webapp開發(fā),混合編程,也會有很多不錯的探索。

未來h5能否通過webassembly撼動原生的大門,讓我們拭目以待。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/92400.html

相關文章

  • 【譯】WebAssembly 初嘗

    摘要:在當前階段,僅僅只是字節(jié)碼規(guī)范。如果都沒有將代碼編譯為字節(jié)碼的工具,要起步就很困難了。接下來要做的是使用將格式的代碼轉換為二進制碼。運行文件,最后就能得到瀏覽器需要的真正的二進制碼。 本文轉載自:眾成翻譯譯者:文藺鏈接:http://www.zcfy.cc/article/1031原文:http://cultureofdevelopment.com/blog/build-your-fi...

    anonymoussf 評論0 收藏0
  • 2018前端值得關注的技術

    摘要:年前端有哪些領域,技術值得關注,哪些技術會興起,哪些技術會沒落。自從谷歌提出后,就持續(xù)的獲得了業(yè)界的關注,熱度可見一斑。就在今年,谷歌也宣布將獲得與安卓原生應用同等的待遇與權限。但是無論都值得關注。 1.前言 2017悄然過去,2018已經來到。人在進步,技術在發(fā)展。2018年前端有哪些領域,技術值得關注,哪些技術會興起,哪些技術會沒落。下面就我個人的判斷進行一個預測判斷,希望能對大家...

    xiao7cn 評論0 收藏0
  • 2018前端值得關注的技術

    摘要:年前端有哪些領域,技術值得關注,哪些技術會興起,哪些技術會沒落。自從谷歌提出后,就持續(xù)的獲得了業(yè)界的關注,熱度可見一斑。就在今年,谷歌也宣布將獲得與安卓原生應用同等的待遇與權限。但是無論都值得關注。 1.前言 2017悄然過去,2018已經來到。人在進步,技術在發(fā)展。2018年前端有哪些領域,技術值得關注,哪些技術會興起,哪些技術會沒落。下面就我個人的判斷進行一個預測判斷,希望能對大家...

    用戶84 評論0 收藏0
  • WebAssembly 系列(六)WebAssembly 的現在與未來

    摘要:目前正在開發(fā)兩個編譯器系統(tǒng)。這就意味著有很多功能還在襁褓之中,沒有經過徹底思考以及實際驗證。這些特性叫做未來特性。實現這一功能將會使用中的,而這一功能的實現將會提高程序執(zhí)行的效率。目前瀏覽器在逐漸支持用標記來加載模塊。 作者:Lin Clark 編譯:胡子大哈 翻譯原文:http://huziketang.com/blog/posts/detail?postId=58ce7fd3a6...

    mcterry 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<