![]() |
設計者 | Mozilla |
---|---|
釋出時間 | 2013年3月21日,11年前(2013-03-21)[1] |
作業系統 | 平台無關 |
網站 | asmjs |
受影響於 | |
JavaScript |
asm.js是一個中間語言,設計目的是使採用C等程式語言編寫的電腦軟件可執行為網絡應用程式,同時效能特徵明顯優於標準JavaScript。
asm.js包括一個JavaScript的嚴格子集,其中的代碼採用具有手動主記憶體管理的靜態型別語言(就像C語言)編寫,代碼使用一個原始碼至原始碼編譯器(例如基於LLVM的Emscripten)翻譯。通過將語言特性限制在適合提前最佳化(英語:Ahead-of-time optimization)和其他效能改進的範圍內,效能得到了提高。
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語言代碼:
intf(inti){returni+1;}
Emscripten將輸出下列JavaScript代碼:
functionf(i){i=i|0;return(i+1)|0;}
注意新增的|0
和去除的類型說明符。在JavaScript中,按位元運算子會將運算元轉換為32位元有符號整數並給出整數結果。這意味着使用0的按位元OR為一個無作用的操作,只是將值轉換為整數。通過對每個參數這樣做,確保了從外部代碼呼叫該函數時,該值被轉換為正確的類型。這也用於返回值,在該情況下確保添加1到i的結果將是一個整數(否則可能變得太大),並標記函數的返回類型。這些轉換為asm.js所必需,這樣最佳化編譯器才可以提前生成高效的本地代碼。在此類最佳化編譯器中,當asm.js代碼呼叫其他asm.js代碼時,轉換不執行,因為必需的類型說明符意味着已保證值具有正確的類型。此外,不同於執行浮點加法和轉換為整數,它可以簡單地執行本機整數運算。這樣一來,它可以得到顯著的效能增益。下面是另一個計算字串長度的例子:
size_tstrlen(char*ptr){char*curr=ptr;while(*curr!=0){curr++;}return(curr-ptr);}
它對應以下asm.js代碼:
functionstrlen(ptr){ptr=ptr|0;varcurr=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++(或其他任何可轉換為LLVMIR的語言)代碼為asm.js的工具。[7]
所有支援JavaScript較新版本的瀏覽器都應該能支援執行asm.js代碼,因為它是該規範的子集。
部分瀏覽器的實現針對asm.js進行了特別最佳化:
目前幾乎所有基於asm.js的應用程式都是使用Emscripten或Mandreel編譯為asm.js的C/C++應用程式。
到目前為止,已有不少程式語言、應用程式框架(英語:Application framework)、程式、函式庫、遊戲、遊戲引擎及其他軟件已被移植。[10]部分名單見下: