asm.js和Emscripten

2012年偶房,Mozilla 的工程師 Alon Zakai 在研究 LLVM 編譯器時(shí)突發(fā)奇想:許多 3D 游戲都是用 C / C++ 語言寫的寞酿,如果能將 C / C++ 語言編譯成 JavaScript 代碼漫贞,它們不就能在瀏覽器里運(yùn)行了嗎革半?眾所周知医增,JavaScript 的基本語法與 C 語言高度相似谆构。

于是,他開始研究怎么才能實(shí)現(xiàn)這個(gè)目標(biāo)铡买,為此專門做了一個(gè)編譯器項(xiàng)目 Emscripten更鲁。這個(gè)編譯器可以將 C / C++ 代碼編譯成 JS 代碼,但不是普通的 JS奇钞,而是一種叫做 asm.js 的 JavaScript 變體岁经。

關(guān)于asm.js的理解

)

asm.js的簡(jiǎn)介

asm.js是一個(gè)中間語言被設(shè)計(jì)用于如C運(yùn)行Web應(yīng)用程序的。同時(shí)保持性能能夠高于標(biāo)準(zhǔn)的JS的計(jì)算機(jī)軟件蛇券。

對(duì)于傳統(tǒng)而言缀壤,C/C++編譯成JS有兩個(gè)最大的困難。

C / C++ 是靜態(tài)類型語言纠亚,而 JS 是動(dòng)態(tài)類型語言
C / C++ 是手動(dòng)內(nèi)存管理塘慕,而 JS 依靠垃圾回收機(jī)制

這里需要說明的是,C是弱類型靜態(tài)語言蒂胞。而js是弱類型動(dòng)態(tài)語言图呢。關(guān)于這方面也查閱了一部分資料。
關(guān)于強(qiáng)弱類型的圖

簡(jiǎn)而言之:

前兩者骗随,弱/強(qiáng)類型指的是語言類型系統(tǒng)的類型檢查的嚴(yán)格程度蛤织。后兩者指的是變量與類型的綁定方法。

弱類型相對(duì)于強(qiáng)類型來說類型檢查更不嚴(yán)格鸿染,比如說允許變量類型的隱式轉(zhuǎn)換指蚜,允許強(qiáng)制類型轉(zhuǎn)換等等。強(qiáng)類型語言一般不允許這么做涨椒。
靜態(tài)類型指的是編譯器在compile time執(zhí)行類型檢查摊鸡,動(dòng)態(tài)類型指的是編譯器(虛擬機(jī))在runtime執(zhí)行類型檢查。簡(jiǎn)單地說蚕冬,在聲明了一個(gè)變量之后免猾,不能改變它的類型的語言,是靜態(tài)語言囤热;能夠隨時(shí)改變它的類型的語言猎提,是動(dòng)態(tài)語言。因?yàn)閯?dòng)態(tài)語言的特性旁蔼,一般需要運(yùn)行時(shí)虛擬機(jī)支持锨苏。

asm.js 就是為了解決這兩個(gè)問題而設(shè)計(jì)的:它的變量一律都是靜態(tài)類型,并且取消垃圾回收機(jī)制牌芋。除了這兩點(diǎn)蚓炬,它與 JavaScript 并無差異松逊,也就是說躺屁,asm.js 是 JavaScript 的一個(gè)嚴(yán)格的子集,只能使用后者的一部分語法经宏。

一旦 JavaScript 引擎發(fā)現(xiàn)運(yùn)行的是 asm.js犀暑,就知道這是經(jīng)過優(yōu)化的代碼驯击,可以跳過語法分析這一步,直接轉(zhuǎn)成匯編語言耐亏。另外徊都,瀏覽器還會(huì)調(diào)用 WebGL 通過 GPU 執(zhí)行 asm.js,即 asm.js 的執(zhí)行引擎與普通的 JavaScript 腳本不同广辰。這些都是 asm.js 運(yùn)行較快的原因暇矫。據(jù)稱,asm.js 在瀏覽器里的運(yùn)行速度择吊,大約是原生代碼的50%左右李根。

值得注意的是
asm.js 沒有垃圾回收機(jī)制,所有內(nèi)存操作都由程序員自己控制几睛。asm.js 通過 TypedArray 直接讀寫內(nèi)存房轿。

var buffer = new ArrayBuffer(32768);
var HEAP8 = new Int8Array(buffer);
function compiledCode(ptr) {
  HEAP[ptr] = 12;
  return HEAP[ptr + 4];
}  

如果設(shè)計(jì)到指針,也是一樣處理所森。

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;
}

Emscripten 編譯器

雖然 asm.js 可以手寫,但是它從來就是編譯器的目標(biāo)語言焕济,要通過編譯產(chǎn)生纷妆。目前,生成 asm.js 的主要工具是 Emscripten晴弃。

emscripten-圖

Emscripten 的底層是 LLVM 編譯器凭需,理論上任何可以生成 LLVM IR(Intermediate Representation)的語言,都可以編譯生成 asm.js肝匆。 但是實(shí)際上粒蜈,Emscripten 幾乎只用于將 C / C++ 代碼編譯生成 asm.js

C/C++ ? LLVM ==> LLVM IR ? Emscripten ? asm.js

圖解asm.js的過程

hello world

#include <iostream>

int main() {
  std::cout << "Hello World!" << std::endl;
}

然后,將這個(gè)程序轉(zhuǎn)成asm.js

$ emcc hello.cc
$ node a.out.js
Hello World!

上面代碼中旗国,emcc命令用于編譯源碼枯怖,默認(rèn)生成a.out.js。使用 Node 執(zhí)行a.out.js能曾,就會(huì)在命令行輸出 Hello World度硝。
注意,asm.js 默認(rèn)自動(dòng)執(zhí)行main函數(shù)寿冕。
emcc是 Emscripten 的編譯命令蕊程。它的用法非常簡(jiǎn)單。

asm.js的用途

asm.js 不僅能讓瀏覽器運(yùn)行 3D 游戲驼唱,還可以運(yùn)行各種服務(wù)器軟件藻茂,比如 Lua、Ruby 和 SQLite。 這意味著很多工具和算法辨赐,都可以使用現(xiàn)成的代碼优俘,不用重新寫一遍。
另外掀序,由于 asm.js 的運(yùn)行速度較快帆焕,所以一些計(jì)算密集型的操作(比如計(jì)算 Hash)可以使用 C / C++ 實(shí)現(xiàn),再在 JS 中調(diào)用它們不恭。

真實(shí)的轉(zhuǎn)碼實(shí)例可以看一下 gzlib 的編譯叶雹,參考它的 Makefile 怎么寫。

參考鏈接

wikipedia - asm.js

wiki地址-Strong typing

wiki地址-Type system

阮一峰老師的網(wǎng)絡(luò)日志

知乎關(guān)于弱類型换吧,強(qiáng)類型浑娜,動(dòng)態(tài),靜態(tài)的區(qū)別--作者:Alan Li

Asm.js: The JavaScript Compile Target, by John Resig

Emscripten & asm.js: C++'s role in the modern web, by Alon Zakai

An Introduction to Web Development with Emscripten, by Charles Ofria

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末式散,一起剝皮案震驚了整個(gè)濱河市筋遭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌暴拄,老刑警劉巖漓滔,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異乖篷,居然都是意外死亡响驴,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門撕蔼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來豁鲤,“玉大人,你說我怎么就攤上這事鲸沮×章猓” “怎么了?”我有些...
    開封第一講書人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵讼溺,是天一觀的道長(zhǎng)楣号。 經(jīng)常有香客問我,道長(zhǎng)怒坯,這世上最難降的妖魔是什么炫狱? 我笑而不...
    開封第一講書人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮剔猿,結(jié)果婚禮上视译,老公的妹妹穿的比我還像新娘。我一直安慰自己归敬,他們只是感情好酷含,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開白布鄙早。 她就那樣靜靜地躺著,像睡著了一般第美。 火紅的嫁衣襯著肌膚如雪蝶锋。 梳的紋絲不亂的頭發(fā)上陆爽,一...
    開封第一講書人閱讀 51,208評(píng)論 1 299
  • 那天什往,我揣著相機(jī)與錄音,去河邊找鬼慌闭。 笑死别威,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的驴剔。 我是一名探鬼主播省古,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼丧失!你這毒婦竟也來了豺妓?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤布讹,失蹤者是張志新(化名)和其女友劉穎琳拭,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體描验,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡白嘁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了膘流。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片絮缅。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖呼股,靈堂內(nèi)的尸體忽然破棺而出耕魄,到底是詐尸還是另有隱情,我是刑警寧澤彭谁,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布屎开,位于F島的核電站,受9級(jí)特大地震影響马靠,放射性物質(zhì)發(fā)生泄漏奄抽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一甩鳄、第九天 我趴在偏房一處隱蔽的房頂上張望逞度。 院中可真熱鬧,春花似錦妙啃、人聲如沸档泽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽馆匿。三九已至抑胎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間渐北,已是汗流浹背阿逃。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留赃蛛,地道東北人恃锉。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像呕臂,于是被迫代替她去往敵國(guó)和親破托。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容