五分鐘瞭解asm.js和WebAssembly
Asm.js是什麼?
相信很多讀者都或多或少地聽說過Asm.js這個名詞,但它究竟是什麼意思呢?
先看一眼官方的定義:
an extraordinarily optimizable, low-level subset of JavaScript
極度優化的、底層的javascript子集。
可以看到主要的三個關鍵詞。
-
極度優化。asm.js是一種提升js執行效率的解決方案。
asm.js能帶來非常高的效率提升。甚至能讓瀏覽器執行3d遊戲。
-
底層的。
底層到什麼程度呢?就相當於是瀏覽器js引擎中的C語言了。
asm.js它的變數一律都是靜態型別,並且取消垃圾回收機制。
當瀏覽器的JavaScript 引擎發現執行的是 asm.js時,就會跳過語法分析這一步,將其轉成組合語言執行。另外,瀏覽器還會通過 GPU 呼叫 WebGL 執行 asm.js,使其執行得更快。
據稱,asm.js 在瀏覽器裡的執行速度,甚至可以達到原生程式碼執行速度的一半。
3. javascript子集。
asm.js雖然語法沒有脫離javascript的範疇,但是javascript中很多語法在asm.js中是不能使用的。
比如asm.js只提供了兩種資料型別:32位帶符號整數和64位帶符號浮點數。其他資料型別,比如字串、布林值或者物件,asm.js 一概不提供。它們都是以數值的形式存在,儲存在記憶體中,通過 TypedArray 呼叫。
asm.js的資料型別
又比如asm.js的變數要求事先宣告型別,並且不得改變。這樣雖然使其喪失了javascript靈動多變的特性,但是就節省了型別判斷的時間,提高了執行效率。
再比如asm.js甚至連垃圾回收機制也拋棄了,所有記憶體操作都由程式設計師自己控制。
如何編寫Asm.js?
雖然名字叫“asm.js”,雖然asm.js也可以直接用javascript來編寫,但是這樣寫出來的程式碼可讀性非常差。
而且asm.js的初衷就是將C/C++程式移植到瀏覽器上來。
所以通常的做法是使用C/C++這樣的靜態型別和手動回收記憶體的語言編寫程式,然後使用編譯器將編寫的程式編譯為asm.js。
Emscripten是目前流行的asm.js編譯器。
Emscripten 的底層使用的是 LLVM 編譯器。通過一系列的處理將C/C++編譯成asm.js。
C/C++ ⇒ LLVM ==> LLVM IR ⇒ Emscripten ⇒ asm.js
Emscripten
asm.js和WebAssembly的異同
WebAssembly和asm.js具有相同的作用,就是C/C++程式碼轉成 javascript引擎可以執行的程式碼。
但asm.js生成的是javascript程式碼,而WebAssembly生成的是WASM格式的二進位制位元組碼。
所以理論上WebAssembly速度更快。
而asm.js的相容性比WebAssembly好,所有瀏覽器都支援asm.js的執行(不談效率)。
發展到現在,Emscripten編譯器也已經支援生成asm.js和WASM兩種格式的程式碼。
asm.js和WebAssembly的作用?
一是可以提高應用在瀏覽器的執行速度。比如遊戲、計算量巨大的演算法等。
二是有利於移植一些C/C++程式碼寫的程式。比如其他語言的直譯器等。
這樣就為瀏覽器提供了更大的可能。可以預見,在不久的將來,人們只要開啟瀏覽器就可以搞定一切工作了。