asm.js
来自维基百科,自由的百科全书
asm.js是一個中間語言,設計目的是使採用C等編程語言編寫的計算機軟件可運行為網絡應用程序,同時性能特徵明顯優於標準JavaScript。
![]() | 此條目翻譯自其他語言維基百科,需要相關領域的編者協助校對翻譯。 |
asm.js包括一個JavaScript的嚴格子集,其中的代碼採用具有手動內存管理的靜態類型語言(就像C語言)編寫,代碼使用一個源代碼至源代碼編譯器(例如基於LLVM的Emscripten)翻譯。通過將語言特性限制在適合提前優化和其他性能改進的範圍內,性能得到了提高。
Mozilla Firefox是第一個實現針對asm.js優化的瀏覽器,從Firefox 22開始使用。[2]
設計
asm.js由JavaScript語言的一個嚴格子集組成。它可以顯著提高採用具有手動內存管理(例如C)的靜態類型語言編寫的網絡應用程序在使用源代碼至源代碼編譯器轉換為JavaScript後的性能。Asm.js的目標並不是提高手寫JavaScript代碼的性能,也不實現增強性能以外的其他目的。
通過將語言特性限制在適合提前優化和其他性能改進的範圍內,其旨在具有比標準JavaScript更接近於本地(原生)代碼的性能特徵。[3]通過使用JavaScript的一個子集,asm.js很大程度上支持所有主要的網頁瀏覽器[4],這不同於WebAssembly或Google Native Client等途徑。
代碼生成
asm.js通常不直接編寫,而是作為一種通過編譯器生成的中間語言,該編譯器獲取C++或其他語言的源代碼,然後輸出asm.js。
例如,提供下列C語言代碼:
int f(int i) {
return i + 1;
}
Emscripten將輸出下列JavaScript代碼:
function f(i) {
i = i|0;
return (i + 1)|0;
}
注意新增的|0
和去除的類型說明符。在JavaScript中,按位運算符會將操作數轉換為32位有符號整數並給出整數結果。這意味着使用0的按位OR為一個無作用的操作,只是將值轉換為整數。通過對每個參數這樣做,確保了從外部代碼調用該函數時,該值被轉換為正確的類型。這也用於返回值,在該情況下確保添加1到i的結果將是一個整數(否則可能變得太大),並標記函數的返回類型。這些轉換為asm.js所必需,這樣優化編譯器才可以提前生成高效的本地代碼。在此類優化編譯器中,當asm.js代碼調用其他asm.js代碼時,轉換不執行,因為必需的類型說明符意味着已保證值具有正確的類型。此外,不同於執行浮點加法和轉換為整數,它可以簡單地執行本機整數運算。這樣一來,它可以得到顯著的性能增益。
下面是另一個計算字符串長度的例子:
size_t strlen(char *ptr) {
char *curr = ptr;
while (*curr != 0) {
curr++;
}
return (curr - ptr);
}
它對應以下asm.js代碼:
function strlen(ptr) {
ptr = ptr|0;
var curr = 0;
curr = ptr;
while (MEM8[curr]|0 != 0) {
curr = (curr + 1)|0;
}
return (curr - ptr)|0;
}
在生成的代碼中,變量MEM8實際上是一個類型緩衝區的逐字節「視圖」,它充當asm.js代碼的堆(heap)。
性能
因為asm.js在瀏覽器中運行,所以性能很大程度上取決於瀏覽器和硬件。編譯為asm.js的C程序的初步基準通常比使用Clang的本地編譯慢一倍以上。[5]
這種超過普通JavaScript的性能增益主要是由於100%的類型一致性以及幾乎沒有垃圾回收(內存是手動管理的大型類型數組)。這個更簡單的模型沒有動態行為,沒有內存分配或釋放,只有一組簡單、定義明確的整數和浮點操作,從而可實現更好的性能和優化潛力。[來源請求]
Mozilla在2013年12月的基準測試顯示:「使用float32優化的Firefox可以運行所有基準,只比原生速度慢不到1.5倍。[6] Mozilla指出本地編譯代碼的性能不是單個度量,而是一個範圍,使用不同的本地編譯器(此例中為Clang與GCC)將提供不同性能的代碼。「事實上,在一些基準測試比如Box2D、FASTA和copy中,asm.js與Clang比較接近,或者比Clang到GCC還接近Clang。在一種情況下,asm.js甚至在Box2D上略微擊敗Clang。」
實現
Emscripten項目提供了可以編譯C和C++(或其他任何可轉換為LLVM IR的語言)代碼為asm.js的工具。[7]
所有支持JavaScript較新版本的瀏覽器都應該能支持運行asm.js代碼,因為它是該規範的子集。
部分瀏覽器的實現針對asm.js進行了特別優化:
- Mozilla Firefox是第一個實現針對asm.js優化的網頁瀏覽器,自Firefox 22開始使用。 OdinMonkey是Mozilla在Firefox中使用的asm.js提前編譯器,它是IonMonkey(SpiderMonkey的JIT編譯器)的一個組件。
- 微軟在Microsoft Edge使用的JavaScript引擎Chakra中實現了asm.js支持,執行驗證以產生高度優化的JIT代碼。[8]
- Google Chrome的V8 JavaScript引擎在Chrome 28中對asm.js基準測試的性能是以前Chrome版本的兩倍以上,[9]儘管Chrome的V8沒有使用提前編譯。
採用
目前幾乎所有基於asm.js的應用程序都是使用Emscripten或Mandreel編譯為asm.js的C/C++應用程序。
- HTML5 Fractal Playground[38] – 繪製迭代函數生成的分形,例如Mandelbrot fractal。
參見
- WebAssembly – 一個開發中的用於瀏覽器的字節碼,旨在比asm.js更快地解析
RPython - CrossBridge
- Google Native Client(NaCl)
參考資料
外部連結
Wikiwand - on
Seamless Wikipedia browsing. On steroids.