WebAssembly:系統編程語言的逆襲

引子

Any application that can be written in JavaScript, will eventually be written in JavaScript. ——Atwood's Law

有人用 JavaScript 做語法詞法解析,有人寫了 x86 模擬器, 還有人用 JavaScript 寫了可自舉的 JavaScript 引擎。JavaScript 早已經在”重新發明一切”的路上一騎絕塵了,JavaScript 的流行也使它始終位於各大語言排行榜上的前列,這無疑是屬於 JavaScript 程序yuan們最好的時代。

這並非是因為 JavaScript 是門優秀的語言 (恰恰相反),而是因為當今的世界是 Web 的世界,Web 的載體瀏覽器只會說 JavaScript。這難免使人眼紅,王侯將相,世人無數次想要取代 JavaScript 的地位,目前為止的歷史我們都看到了,無一不鎩羽而歸。求上不得,得其中,最新成果是大家(夥兒)齊心協力把 JavaScript 變成了新一代的彙編語言。請移步這裡看大家的最新成果。

WebAssembly:系統編程語言的逆襲

WebAssembly

去年 11 月 13 日,Mozilla 在其官方博客上發表了一篇文章,WebAssembly support now shipping in all major browsers,指出當今世界四大主流瀏覽器 Firefox,Chrome,Safari,Edge(排名分先後),都已經支持了名為 WebAssembly 的新技術,並回顧了一路走來的艱難歷程。最後指出這是新時代的開端,大家一起歡呼吧。那麼,WebAssembly 到底是啥?讓我們發出發聾振聵的三連問:

可以吃嗎?

請移步 WebAssembly 官網。官網解釋如下:

WebAssembly or wasm is a new portable, size- and load-time-efficient format suitable for compilation to the web.

關鍵詞:

  1. 可移植: WebAssembly 是一種可移植的二進制格式,它不依賴於具體的瀏覽器平臺。
  2. 高效:WebAssembly 被設計為針對 Size 和 Load Time 進行優化的格式,可以在各個硬件平臺上以 native speed 運行。
  3. 安全:WebAssembly 是運行在沙盒內的,甚至可以和當前的 JavaScript 虛擬機共享一套環境,並且也遵守瀏覽器各種跨域不跨域的規章制度。
  4. 開放:WebAssembly 是開放標準,不受某一家廠商控制(Oracle你聽到了嗎)。並且被設計為可以和 JavaScript API 和 Context 交互。

簡而言之,WebAssembly 可以被看做是通過瀏覽器運行的某種高效的開放的二進制格式,並且可以和 JavaScript 環境互通。

WebAssembly 的目的是取代 JavaScript 嗎?FAQ 這樣回答:不,WebAssembly 是被設計來補充而不是替代 JavaScript。隨著時間推移,越來越多的語言可以被編譯為 WebAssembly,但是 JavaScript 還是作為 Web 唯一的動態語言而存在。

這樣看來老二的位置擺得很正嘛。對於 WebAssembly, 筆者最看重的一點是作為開放標準的同時有粗大腿的支持 (M$ Google Apple Mozilla),這才是它有可能活下來的原因。問題是可以吃嗎,答案當然是可以吃(佛系碼農也可以不吃)。

怎麼吃?

WebAssembly 同時存在一個二進制格式和一個文本的描述格式,這很像是機器語言和彙編語言的關係。這裡我們用一個例子解釋一下。

WebAssembly:系統編程語言的逆襲

事實上,WebAssembly 可以被看作是運行在一個 structured stack virtual machine 裡,懂行的朋友一眼就可以看出這和 Java bytecode 非常的像。所以大家不要以為 WebAssembly 是在重新發明 Flash 了,這貨明明是在重新發明 Java Applet 啊,好吧 Silverlight 也有點像...。順帶一提,Android 的 Dalvik 為了效率,使用的是 register-based virtual machine。對 WebAssembly spec 感興趣的朋友可以移步這裡。

作為 WebAssembly 的 MVP,C/C++ 及其類庫的支持是首當其衝的。因為基於 LLVM 的平臺,所以理論 LLVM 支持的語言都可以編譯為 WebAssembly,C/C++,rust,甚至 .net 和 Java 也可以編譯到 WebAssembly,只不過託管語言都需要附帶一個巨大的runtime。

下面我們以 C/C++ 為例,我們寫一個函數給 JavaScript 使用。

步驟:

  • 安裝 WebAssembly 構建工具鏈 emscripten,針對 macOS,請參考這裡
  • 安裝後,執行 emcc --version 判斷是否成功
  • 創建 C++ source:cat random.cc
WebAssembly:系統編程語言的逆襲

這裡用 C++ 產生一個正態分佈,期望為0,方差100的隨機數,然後導出為一個 C 函數 normal_rand

執行 emcc --bind -std=c++14 --emrun -s WASM=1 -s EXPORTED_FUNCTIONS='["_normal_rand"]' -O3 -o random.html random.cc順利的話會在當前目錄生成如下文件

WebAssembly:系統編程語言的逆襲

random.wasm 就是我們的 WebAssembly,random.js 和 random.html 是模板代碼,幫助我們加載 WebAssembly。

執行 emrun --no_browser --port 8821 random.html 啟動一個 WebServer

用支持 WebAssembly 的瀏覽器訪問http://localhost:8821/random.html,然後在 console 裡面執行 Module._normal_rand() 即可看到結果

怎麼做好吃?

古往今來,在瀏覽器裡面嘗試改善 JavaScript 性能和增強功能的嘗試大約都失敗了吧,前有 ActiveX,Java Applet,Flash,後有 Silverlight,Flex,NaCl。WebAssembly 應該是各個瀏覽器大佬的最新嘗試。不過這次大家都學乖了,沒人指(xi)望一個私有標準會成功,於是聯合起來開發一個開放的標準。

至少目前看來,結果還是很讓人欣喜的。因為開放標準的緣故,除了上面的 emscripten,還有大量的工具開始支持 WebAssembly,甚至 clang 可以直接指定 target 為 WebAssembly。加上瀏覽器把諸如 DOM API 以及 WebGL API 都暴露給了 WebAssembly,應用場景相當可觀。首當其衝的就是遊戲廠商,Epic 和 Unity 都是 WebAssembly 的早期嘗試者,他們已經把自己的遊戲引擎移植到 Web 平臺而不用重寫代碼。不僅如此, WebAssembly 還支持 non-web 的場景,比如 NodeJs 也開始支持 WebAssembly。WebAssembly 官網有個 use case 清單,列舉了可能的應用場景。圖形圖像的處理,計算機輔助設計,AR/VR,VPN,加解密等等。到那時,前端可以玩出的花樣,想象空間實在太大。

有點過於美好了哈,我們還是就此打住,拭目以待吧。

Reference

這裡列舉一些 WebAssembly 相關的資源,各位隨喜:

  1. Funky Karts, 移植到 WebAssembly 的網頁遊戲,作者在網站記錄了學習 WebAssembly 到移植成功的全過程。
  2. WasmExplorer,在線的 C/C++ to WebAssembly 編輯器,同時也可以查看 Assembly 內容。
  3. WasmFiddle,另一個在線編輯 WebAssembly 的工具
  4. WasmRocks WebAssembly 新聞站。
  5. emscripten 官網。

文/ThoughtWorks李好

原文地址:https://insights.thoughtworks.cn/webassembly-system-programming-language/


分享到:


相關文章: