WebAssembly的過去、現在和未來
歷史

在每個瀏覽器裡面,無論Chrome,Firefox,Safari,Edge,能夠執行的語言就是Javascript。為了能夠讓其他語言的程式碼在瀏覽器中執行,WebAssembly被創造出來。它擁有更好效能,更小的size,能夠更快的載入和執行。我們無需編寫WebAssembly的程式碼,只需要將其他高階語言編譯成WebAssembly,這樣就能在瀏覽器中複用大量的其他語言現有的程式碼。
WebAssembly仍在持續的發展,還有大量的特性即將到來。其最早發明出來是為了將C++的轉譯成JS,然後在瀏覽器中執行起來,這樣就能把大量現有的C++程式碼在瀏覽器中複用。被轉譯後的JS程式碼比原生的JS程式碼要慢,Mozilla的工程師發現一種型別系統,可以讓被轉譯後的JS ofollow,noindex">執行得更快 ,這就是 asm.js . 同時,其他瀏覽器廠商發現asm.js的執行速度非常快,也把這種優化加入到 他們的瀏覽器引擎中 。這僅僅是開始,工程師們仍在持續努力,但是,不是將其他語言編譯成JS,而是一種新的語言,那就是WebAssembly。
最小可用產品

WebAssembly不僅僅支援C/C++,同時也希望支援更多的高階語言,因此,需要一個語言無關的編譯目標,就像組合語言一樣,支援任何語言編譯成組合語言。這個編譯目標有如下的特點:
- 跟具體的平臺無關,因此不同平臺的不同瀏覽器都能執行WebAssembly。
- 擁有足夠快的執行速度,能夠帶來足夠流暢的互動體驗。
- 載入速度要足夠快,因此,需要編譯目標能夠被壓縮,減小載入內容的大小
- 能夠手動的管理,分配記憶體。我們知道C/C++一類的語言支援指標的特性,通過指標可以讀寫特定地址的記憶體;為了安全考慮,還要對限制特定地址的記憶體進行操作。出於以上的亮點,WebAssembly使用了線性記憶體模型。
通過以上的特點,保證了WebAssembly能夠在生產環境中使用起來。
如何應對繁重的桌面應用

我們知道,大量的桌面應用,像PS,AutoCAD,這些應用非常的龐大,對效能要求非常苛刻。要先讓他們在瀏覽器裡面執行起來非常的難,因此需要更多的特性來確保更佳的效能:
- 首當其衝的,是需要支援多執行緒。現代的計算機都是多核的,通過多執行緒能夠更好的利用計算機的計算能力。
- SIMD(單指令多資料)。通過SIMD,能夠將一組記憶體劃分成不同的執行單元,就像多核一樣。
- 64位定址。藉助64位定址,能夠使用更多的記憶體,這對一些記憶體敏感性的應用是非常有利的。
- 流式編譯。前面提到了,提升載入的速度,其實我們有更好的辦法,就是剛下載的時候就開始編譯,這將是巨大的提升。
- HTTP快取。如何兩個瀏覽器載入相同的WebAssembly程式碼,將會編譯成相同的機器碼,因此可以將編譯後的機器碼儲存在HTTP快取中,這樣就可以跳過編譯的過程,複用機器碼。
現狀
- 多執行緒: 一個草案 已經接近完成,其中的關鍵SharedArrayBuffers,已經被否決了。
- SIMD:正在開發中...
- 64位定址: wasm-64 即將登場
- 流式編譯 :Firefox已經在2017年支援,其他瀏覽器也即將支援
雖然這些特性仍在開發中,但是我們能夠看到已經有大量的桌面應用在瀏覽器中執行起來,其中最大的幕後功臣就是WebAssembly。
WebAssembly與JavaScript

對於很多的web應用場景,我們可能只需要在一些效能敏感的部分,使用WebAssembly。因此,某些模組需要用WebAssembly來編寫,然後替換掉那些JS寫的部分。一個例子就是Firefox中的source map library的parser,它用WebAssembly編寫,比原來用JS編寫的快11倍。為了能讓這種場景下,WebAssembly更好的發揮作用,有更多的要求:
- JS和WASM能夠更快的相互呼叫。因為要將WASM程式碼作為模組繼承到現存的JS應用中,需要他們能夠更快的相互呼叫,Firefox中已經有了巨大的 提升
- 快速而容易的資料轉換。在JS和WASM相互呼叫時,需要傳遞資料,要想實現上面的兩個目標,非常的難:WASM只理解數字,那就需要將各種資料格式轉換成數字
- ES module。整合WASM模組,通常在JS中使用import,export關鍵詞,因此,瀏覽器需要內建ES module。
- 工具鏈。在JS中,可以使用npm,brower等工具,但是在WASM中,好像沒有這個工具...
- 相容性。前端開發,都逃不了相容性的問題。
現狀
- Firefox中,JS和WASM能夠很快的 呼叫
- 引用型別草案登場 ,其增加了一種新的,WASM函式能夠接收和返回的型別,這個型別引用一個外部的object,可以是JS的Object。
- 一個 ES module的草案 被提及,瀏覽器廠商正在支援。
- Rust生態的wasm-pack能夠像npm一樣支援包管理
- 藉助wasm2js工具,能夠讓WASM在舊版的瀏覽器中得到支援
通過以上的特性以及正在開發中的功能,WASM的能力得到釋放,接下來就是如何再現有的Web生態中使用WASM。
應用

在前端開發中,大量涉及的框架及編譯成JS的語言都將是WASM發揮作用的場景。所以就有兩種選擇了:1,使用WASM來重寫現有的Web框架;2,將Reasonml,Elm等語言編譯成WASM。為了實現這些功能,需要WASM提供更多高階語言的特性,包括:
- GC。首先,提供GC功能對重寫web框架是非常有優勢的。例如:使用WASM重寫React中的diff功能,藉助多執行緒,手動的記憶體分配,能夠提供以前無法現象的高效能,但是當你跟JS 物件互動時,例如元件,仍然需要GC來減輕開發的負擔。
- 異常處理。很多的高階語言,如C/C++提供異常處理,在某些特定場景下非常有用,同時JS也有異常處理,當WASM和JS互操作時,也需要有異常處理的支援。
- debug。這個就不多說
現狀
- JS擁有 Typed Objects 草案 ,WASM擁有 GC草案 。通過這兩個草案,JS和WASM都能夠清晰的知道一個物件的結構以及如何去儲存,使用,回收。
- 異常處理 。目前還在開發階段。
- debug。目前,大多數瀏覽器已經支援。