這是一個由 simviso 團隊對2019 Google I/O 大會中關於面向Web開發人員的WebAssembly相關話題進行翻譯的文檔,內容並不是直譯,其中有一些是譯者自身的思考。Surma是Google公司WEB基礎的貢獻者,也是open web平臺的開發倡導者。javascript
視頻地址:面向Web開發人員的WebAssembly 2019 Google I/O 上java
視頻翻譯版權歸 simviso 全部git
本次參與翻譯人員github
我是Surma,我是open web平臺的開發倡導者,在倫敦與谷歌的Chrome團隊合做。 今天很高興能夠跟你們談一談我最近發現的一個讓我充滿激情的東西,那就是webassembly。web
你可能對它有所耳聞,若是你之後有什麼問題的話,能夠在 Twitter 上聯繫我。稍後個人同事,即來自web工程團隊的 Deepti 會分享一些關於WebAssembly將來的話題。在咱們開始講以前,我想讓你們一塊兒看下這張圖。算法
由於 WebAssembly 一般與 C++ 緊密相連,以致於不少人都認爲它都是關於 C++ 的,事實上,WebAssembly 遠不止於此。 你能夠在網上找到不少關於 C++ 和 Emscripten 的 demo。 這頗有意義,由於 Emscripten 是一個使人驚歎的工具。但對Web開發人員而言,意識到WebAssembly不只限於C++,這點很關鍵!WebAssembly 自己實際上是一個很是有用的工具,你值得擁有!這就是我想在此次演講中談論的內容。 我想展現一些支持 WebAssembly 的其餘語言,以此來讓你在不學習新語言的狀況下使用WebAssembly 。編程
而後,就像我說的,Deepti 接下來將討論 WebAssembly 的將來。canvas
因此要確保每一個人都知道或者但願在場的人都知道這個網站(WebAssembly官網),它上面解釋了什麼是 WebAssembly,它是一個基於堆棧的虛擬機。api
若是你不知道什麼是基於Web 堆棧的虛擬機,那也沒有關係。 重要的是,你能意識到它是一個虛擬機, 意味着它不是一個實際存在的處理器,它的設計理念在於 咱們能夠很容易的將通用代碼編譯到真實的運行環境下可執行的代碼,這就是所謂的可移植性。所以,對虛擬機而言,設計之初須要優先考慮可移植性。數組
所以,當你使用任意語言編寫某些代碼並將其編譯到 WebAssembly 時,也就是說這些代碼會被編譯成虛擬機可執行的指令集,而後將這些指令存儲到以二進制格式存儲到.wasm
文件中。
由於該虛擬機能夠很輕易的根據對應平臺下的處理器進行代碼編譯,因此.wasm
文件能夠在運行時被讀取,此時咱們這裏運行的上下文極有多是瀏覽器。 瀏覽器能將.wasm
文件轉換成當前機器可執行的機器碼,並在瀏覽器上執行該代碼。
在一開始,webassembly就是爲了面向過程安全而設計的。你能夠在裸機上運行該代碼,但這並不意味着它是不安全的。
實際上咱們已經在上次的Google I/O 大會上討論過WebAssembly了。 做爲一項技術,它以驚人的速度快速成長,並佔據了一席之地。以前咱們也討論了一些大公司是如何使用webassembly來運行他們以前已經存在的一些產品,這些產品極可能是用C++來編寫的。
舉個例子,就拿咱們使用多年的AutoCAD來說,這是一個很是知名的產品,但如今他們正努力將它編譯到Webassembly上,當你想用它時,你就能夠當即在瀏覽器上運行它,想一想都使人感到難以想象。
另外一個例子則是Unity遊戲引擎以及虛幻引擎,它們如今都已經開始支持webassembly。 一般這些遊戲引擎已經內建了一套抽象,由於你須要將你的遊戲構建並編譯到PlayStation,XBox或者其餘遊戲平臺之上。
但如今WebAssembly已經成爲它們的另外一個編譯目標,那給咱們印象很深的就是經過瀏覽器和Webassembly就能夠提供這些遊戲運行所需的性能。
這讓我以爲很神奇,這些神奇的事情還在繼續發生着。
你經過WebKeynote就能夠看到,個人同事Paul Lewis創建了一個感知工具包,它能夠幫你創建一種沉浸式的體驗。他們但願經過二維碼和圖像檢測的形式來和咱們的現實世界創建聯繫。
因此瀏覽器可以經過使用圖形檢測API(Shape Detection API)檢測二維碼,但並不是每一個瀏覽器都能實現了這一功能。
因此他們要作的就是該經過什麼途徑使用這個圖形檢測API。若是不可用,他們能夠經過將二維碼庫編譯到webassembly上,而後就能夠按需加載。這樣咱們就能夠找到它。
而且圖像檢測根本不在Web平臺上。 因此他們須要本身去構建,並使用 Webassembly 爲瀏覽器提供新的功能。
UI工具包QT(QT是跨平臺的軟件開發工具包)宣佈他們如今也支持 WebAssembly。 所以這也意味着其實你如今可使用一箇舊版本的Lib QT應用程序, 並將其編譯爲 WebAssembly。 而後在瀏覽器標籤體驗中有一個奇怪的窗口,這看起來不太理想,這裏只是爲了代表它起做用了。
但QT是一個強大且通用的UI庫。 因此,他們網站底部有不少Demo,實際上他們使用 Lib QT 和WebAssembly構建了一種優良且原生的UI。
因此若是你對 WebAssembly 不甚瞭解,那麼你可能會問它們是怎麼作到的? 針對這些例子,給出的答案是Emscripten
。
Emscripten的目標是替代C或C++編譯器,取代將代碼編譯成你所需的本地機器碼,而是將代碼編譯到webassembly上。 他們真的嘗試着進行這方面的取代工做。不管你編寫什麼語言的代碼,均可以跑在一個系統上,便可以很神奇地在web上面運行。這也是兩種編譯器之間最明顯的區別。
爲了實現這一目標, Emscripten 在幕後作了不少繁重的工做。
我之因此這麼思考的緣由,在於它在這麼多種狀況下均可以很緊密和webassembly一塊兒很好的工做
最初,Emscripten 是一個asm.js編譯器。 這是Mozilla的一個概念,他們編寫了這個編譯器,用於將C語言代碼並將其轉換爲 JavaScript。
所以能夠看到,右手邊的這個就是asm.js。 它只是普通的 JavaScript,也就是說,只要能夠執行 JavaScript 的瀏覽器均可以執行asm.js。
但這個計劃旨在讓其它瀏覽器支持asm.js,從而讓它們運行這類程序的時候更加快速。 因此你須要分配一塊內存,同時接收一些變量。瞬間,你的C++ 代碼就可以運行在你的 JavaScript 引擎上!
但 C 和 C++ 常用其餘API,好比 fileopen 和 OpenGL。 所以,Emscripten 可使用 WebGL 假裝成 OpenGL ,也能夠經過模擬一個文件系統,使你看起來好像在處理真實的文件同樣。 基本上,他們是真模仿一整套POSIX操做系統來使代碼運行在 Web 上,而這些代碼歷來都不是爲 Web 編寫的。 因此他們作到了!
因此當 WebAssembly 出現時,對Emscripten來說, 只是添加了一種新的輸出格式,依然保留着他們在進行模擬時能夠作到的全部功能。 所以,Emscripten 能夠按照以前的經驗進行使用。
咱們知道,將 POSIX 代碼經過WebAssembly在 Web 上運行。 這樣,他們就可以以極快的速度圍繞 WebAssembly 來提供很是使人印象深入而且成熟的Demo和工具。
他們值得獲得你們的稱讚,由於他們,全部其餘語言有了這樣一個平臺。 我想這就是爲何 WebAssembly 與 C++ 如此緊密的緣故,在於 Emscripten 的快速成熟的發展。
可是 對於Web 開發人員呢?
可能你是在 Web 機構工做或者你也多是一個自由開發者 WebAssembly 對你會有什麼樣的幫助?你必需要學C++嗎? NO!
當你是一個Web開發人員,你會想,Oh,我應該須要學習 C++的,只有這樣你纔可使用 WebAssembly,可能不少人都會這樣想。
由於當你知道JavaScript的時候,你在想C++究竟是什麼?有趣的是,反過來也是同樣。當我看到C++開發人員第一次看到或寫JavaScript代碼時,他們的表情如出一轍。
我不是說由於一種語言比另外一種語言好,僅僅是由於他們須要這樣一種大相徑庭的思惟方式來編寫代碼。 這兩種語言我寫的都很專業。但每當我稍微切換一下,老是須要一些時間才能想到(思惟方式的不一樣)。我想說的是,對於Web開發人員來講,至今尚未去學習 C++ 的動力。
所以,這兩種編程語言都掌握很是好的人很是少。這就致使,webassembly彷佛是一個很是小衆的技術。實際上,它是一個很是有用且值得你擁有的工具!
這裏,我想說的是,每當我想到 Webassembly 時,我一般會經過兩個主要例子來討論。 一方面,我想談談在 JS 應用程序中微小模塊的替換、熱傳遞和 WebAssembly 的瓶頸,同時也想談談 Webassembly 比 JavaScript 更快的神奇之處。
但首先,我想談談關於生態系統的其餘方面。
這看起來有點奇怪,由於當我說 JavaScript 生態系統很是龐大時,沒人會反對。 個人意思是,僅僅只是在NPM上看,它就很是巨大。 但事實上並非每一個主題的首選都是 JavaScript,也有多是其餘語言。
因此有時候你可能會去面臨一個問題,你須要尋找庫去解決這些問題。你能夠在 C 中或者 Rust 中找到這些答案,而不是在 JavaScript 中找到。
所以,你要麼坐下來編寫本身的 JavaScript 對應實現,要麼經過WebAssembly來使用其餘語言的相關實現。 這正是咱們對 Squoosh 所作的。
Squoosh 是一個徹底能夠在瀏覽器中運行的圖像壓縮應用程序,能夠在脫機狀態下工做。你能夠放入圖片,而後可使用不一樣的編解碼器壓縮它們。 以觀察這些不一樣的編解碼器如何對你的圖片的視覺質量產生不一樣的影響。 若是你瞭解的話,能夠發現瀏覽器如今已經提供了這一性能。
經過使用 Canvas,你能夠決定你要對圖片進行編碼的圖片格式。 你甚至能夠控制圖片質量!
但事實證實,瀏覽器經過對這些編解碼器的優化而不是優化壓縮質量或視覺質量來提升壓縮速度。 老實說,有點不盡人意。 並且,你有點受瀏覽器支持的編解碼器的約束。
因此直到最近,也只有 Chrome 能夠編碼爲 WebP 格式,其餘瀏覽器卻沒有。 因此這對咱們來講還不夠。
咱們利用谷歌查閱了一些相關資料,並找到了一些使用 JS 寫的有關 JPEG 的編解碼器 但有點奇怪,咱們並無找到一個使用JavaScript寫的專門針對WebP 的編碼器。 所以,咱們認爲咱們得看看其餘東西。。
因此咱們從其餘地方查閱了一番,並在C和C++中找到了大量的相關編碼器。 所以,咱們選擇WebAssembly 因此呢,咱們要作的就是編譯。
舉個例子,將MozJPEG 這個庫編譯到WebAssembly上,並加載到瀏覽器中,而後將瀏覽器的JPEG 編碼器替換成咱們本身加載的這個這樣咱們在相同視覺質量下獲得了更小體積的圖片,酷吧! 不只如此, webassembly還容許咱們加載這個庫所暴露的專業選項,而這些在瀏覽器中顯然是不可能暴露的。
所以,配置諸如色度子採樣或者不一樣的量化算法等選項,不只有助於將最後幾個字節從圖片中捨棄,並且還能夠做爲一種學習工具,方便咱們去查看這些選項到底是怎麼影響咱們的圖片視覺和文件大小的。
這裏的重點是咱們採用了一段舊代碼,彷彿 MozJPEG 又回到了1991年(mozjpeg裏面有個頭文件是在1991開始的)
它絕對不是以 Web 爲目的寫的,但咱們仍是將它使用在了 Web 上,並用它來改善 Web 平臺。
還有咱們用過的 Emscripten。 因此將它與 Emscripten 一塊兒向你展現它是如何工做的。
我一般會分兩步進行。
第一步是編譯庫,以便稍後你能夠連接到它。 圖片編解碼器一般會用到多線程和 SIMD(單指令多數據流),由於圖片壓縮是一個高併發任務。 但無論是 JavaScript 仍是 WebAssembly 都還不支持多線程或 SIMD。稍後Deepti 會帶着你們來討論這方面的內容。
可是這裏咱們經過禁用SIMD 以確保在運行過程當中不會出現任何問題
在第二步中,咱們須要寫一段橋接代碼這個函數我稍後將使用JavaScript來調用, 因此,它須要接收圖片、圖片尺寸,而後經過MozJPEG 來對它進行壓縮,並返回一個包含JPEG 圖片的數組類型Buffer。
當咱們寫完這段橋接代碼,咱們調用EMCC(Emscripten Compiler Frontend )命令,Emscripten C編譯器將編譯咱們的C++文件和庫文件,而後連接到一塊兒供後續使用。 這個過程沒有報錯,而後獲得輸出文件:一個已經配置好了的JS文件和對應的webassembly文件。這裏要記住,Emscription做爲一個替代者,已經將Emulations相關的複雜工做全都幫你作了(Emulations 是C++11的一個庫) 你須要一直關注你文件大小,由於這種文件系統emulations 相關api代碼須要其餘的相關底層輸入。 所以若是你使用了大量的C語言的API,那麼生成的文件將會很大,尤爲是JS文件。
咱們一直在與Emscripten團隊密切合做,爲了讓生成的文件儘量的小。 可是若是你想讓Emscripten成爲一個替代品,你只能盡你所能作的更多。 因此仍是要注意生成文件的大小。
關於WebAssembly 的另一個例子就是使用Squoosh進行圖片的縮放。 爲了將一張圖片放大或者縮小, 有不少方式能夠經過許多不一樣的視覺效果和視覺輸出來實現這一點。 能夠經過多種不一樣的視覺效果和視覺輸出進行實現。
所以對於瀏覽器,若是你只是使用瀏覽器縮放圖片,你會獲得一張縮放的圖片。 它可能會很快,可能看起來也不錯。 但有時候經過對這張圖片縮放操做進行不一樣的變量控制真的能夠產生巨大的視覺衝擊力因此,在這個視頻上,你能夠看到我在 Lanczos3 和瀏覽器擁有的算法之間來回切換。 你能夠看到,經過Lanczos3算法,我會有一個線性RGB色彩空間轉換。
實際上,我對這張圖片中的亮度有更真實的感知。 因此在這種狀況下,它其實是一段很是有用的代碼。 咱們在 Squoosh 中使用的這些圖像縮放算法,其實是從 Rust 生態系統中提取的。
Mozilla 爲 Rust 生態系統進行了大力投資, 他們的團隊爲 Rust 編寫了 WebAssembly 工具,同時社區也將這些東西抽象爲通用工具。 其中一個工具是 wasm-pack,它真的很趁手,能夠幫你將你的 Rust 代碼轉化爲 WebAssembly 模塊,一個現代化形式的 JavaScript(譯者注:JS能夠調用.wasm文件,變相對功能拓展,因此稱之現代化) ,而且它很是小。 我以爲這種東西真的頗有趣。
因此對於Rust,一樣的道理,咱們有一個庫,用來編寫咱們這麼一小點橋接代碼。
在這個例子中,我想經過JS調用這個resize函數。它經過接收圖片、我輸入的圖片大小和輸出的大小,而後經過這個函數我會獲得調整後的圖片。
而後你就能夠將全部這些代碼經過wasm-pack轉換爲一個咱們可用的webassembly模塊, 如今比較文件大小有失公平,由於它是一個不一樣的庫,並且這個庫相對較小。
因此不能直接從文件大小層面比較。可是就平均而言,講道理說,Rust每每會產生更小的膠水代碼。由於Rust沒有作任何關於POSIX的文件系統模擬
你不能在rust使用關於文件的函數,由於它根本就沒有作文件系統模擬。 若是你想要的話,也能夠放入一些它們提供的封裝模塊。它更像是一種可插拔的配置。
所以,最低咱們也要用到 Squoosh,也就是咱們須要使用至少來自兩種不一樣語言的四個不一樣的庫。 這些庫與web 無關,但咱們仍然繼續要在web上使用它們。
這正是我想要你從這整件事中獲得的東西,若是你在Web平臺上發現一個(技術)空白,而且該空白其餘語言已經實現了不少次,但卻不是用於Web上或者不是經過JavaScript實現的。WebAssembly 多是一個工具。
但如今讓咱們來談談在你的 JavaScript中關於Hot Path(有大量循環迭代的代碼實現)的替換,以及 WebAssembly 比JavaScript 更快的神奇之處。
如今這對我來講很是重要,而這就是爲何我想出了使用這張圖來表達個人意思。
JavaScript 和 Webassembly 都有相同的峯值性能。 它們運行都很快,可是在運行比較穩定的代碼(fast path)這點上,使用 Webassembly比JavaScript快得多(譯者注:fast path 是已經編譯後的代碼,slow path是須要臨時進行編譯的代碼)
fast path: Frontend -> simple code generator -> assembler
slow path: Frontend -> IR optimizer (sometimes more than one level of IR) -> code-generator -> assembler
複製代碼
或者反過來說,若是你運行一些不穩定的代碼(slow path),相比WebAssembly 而言,js就更加容易出現一些意想不到的意外。
目前,WebAssembly 正在尋找支持多線程和 SIMD 的解決方案,而這是JavaScript 永遠作不到的
所以,一旦這些技術實現,WebAssembly 將有機會真正的超越 JavaScript 。但在目前狀態下,它們的峯值性能都是相同的。
爲了理解在Fast Path環節下JS的總體性能降低,讓咱們來談談一點關於Chrome 的 JavaScript V8引擎 和 WebAssembly 引擎吧。
JavaScript 文件和WebAssembly 文件有兩個不一樣的引擎入口點。 JavaScript 文件傳遞給V8的解釋器:Ignition。 因此,它能夠將JavaScript 文件做爲文本讀取,並解析和運行它。
當這個解釋器運行時,它會蒐集有關代碼行爲的分析數據,而後經過Turbofan這個優化編譯器來生成機器碼。
另外一方面,webassembly文件將會傳給Liftoff這個流式webassembly編譯器
一旦這個編譯器完成操做,turbofan 就會啓動並生成優化代碼。 這裏有一些區別。 第一個明顯的區別是他們有不一樣的名稱和不一樣的Logo,但也有概念上的區別。 ignition是一個解釋器,Liftoff是一個生成機器代碼的編譯器。雖然咱們不能老是以偏概全的去說機器碼永遠要比解釋性程序代碼跑得更快。 但總的來說,確實是這麼一回事。
那麼,第一個區別就是速度感知方面
但更重要的是JavaScript的這一區別。 但對於JavaScript來說,更重要的區別是優化編譯器只會在最後啓動,在這以前JS代碼必須進行運行並進行觀察才能被優化。由於某些假設是根據觀察結果得出的。 生成機器碼,而後再運行機器碼。 可是一旦這些假設沒有辦法再Hold住情況,你必須回到解釋器。由於咱們不能再保證機器是否能夠正常工做。這被咱們稱爲deopt
,即負優化。
有了WebAssembly,Turbofan老是在Liftoff編譯器以後起做用,而且你能一直留在Turbofan 上輸出。
你能一直留在fast path 上,而且你永遠不會出如今deopt情況,我想這也是你們對於WebAssembly速度更快這個觀點的在認知上的誤區。
在Javascript上你會很容易就獲得deopt狀態,而在WebAssembly上就不會。
來自Rust WebAssembly 團隊的 Nick Fitzgerald 其實作了一個很是好的基準測試,他爲JavaScript 和 WebAssembly 編寫了一個基準測試。
圖中JavaScript是紅色部分,WebAssembly 是藍色部分,運行在不一樣的瀏覽器上。 看到這裏,你會說Yes,OK,WebAssembly 更快。
可是這裏主要的時間消耗能夠看出JavaScript消耗跨度比較大。 它須要多長時間纔是不可預料的,而不管在哪一個瀏覽器上WebAssembly始終如一,消耗的時間基本相同。
我想這纔是關鍵,這也是我想帶給大家的。WebAssembly 爲你提供了可預測性更強的性能。 它提供了比 JavaScript 可預測性更強的性能。
這就是我想經過Squoosh這個例子來告訴你們的東西, 咱們想旋轉一個圖片。 因此,咱們想好了,咱們用 Canvas 實現吧。可是咱們不能使用它,由於Canvas 運行在主線程上。
在Chrome中的OffscreenCanvas不多運行在主線程上 (譯者注:OffscreenCanvas提供了一個能夠脫離屏幕渲染的canvas對象,是針對上面提到的主線程的補充)
因此,咱們最終手寫了一段 JavaScript 來旋轉它或者只需從新排列像素便可旋轉圖片。 它真的很管用,很是快,但事實證實,咱們在其餘瀏覽器測試得越多,它就變得有點奇怪。
因此在這個測試案例中,咱們將一張4K分辨率的圖片進行旋轉。
這不是爲了比較瀏覽器。而是關於比較 JavaScript 的。最快的瀏覽器須要花費400毫秒, 最慢的瀏覽器須要8秒, 甚至在脫離主線程的狀況下,對於用戶來講,按下按鈕旋轉圖像消耗的時間實在太長了。
從這裏你切實能夠看到,很明顯,咱們能夠在一個瀏覽器中停留在fast path 上,但咱們在另外一個瀏覽器中卻失敗了。 不是這個瀏覽器不夠快,只是一些瀏覽器的優化有所不一樣。
因此,咱們將咱們寫的旋轉代碼運行在WebAssembly 上或經過其餘語言實現這段代碼並編譯到WebAssembly ,而後來進行性能比較。
你能從這幅圖中看到什麼? 幾乎全部支持WebAssembly 的語言都能使咱們的運行時間下降到大約500毫秒左右。我認爲這是可預測的。 個人意思是這些語言仍然存在一些差別, 但拋開JavaScript的數據,其它的就沒什麼差距, 這簡直是指數級的下降。
一樣,咱們也能夠從這裏看到,我有注意到在WebAssembly 最優性能體現這塊, WebAssembly和JavaScript的最優性能幾乎是同樣的。
AssemblyScript是一個從TypeScript到WebAssembly的編譯器。
這麼說可能會誤導你, 由於你不能將你現有的 TypeScript放到這個編譯器中,並從中獲取WebAssembly 。由於在WebAssembly 中你沒有Dom API, 這樣你就不能只使用相同的代碼。 可是AssemblyScript 可使用TypeScript語法寫的不一樣類型的庫
這也就意味着你根本不須要去學一門全新的語言用來寫WebAssembly,這也是讓我感到最爲驚豔的一點 因此這看起來像什麼,就是Typescript語言,只不過有一點點區別 就好像圖中的i32
,它實際上並非JavaScript中的一種類型,但它倒是WebAssembly的一種所屬類型。
而後,如load和store這些內置函數,能夠從內存中讀取和寫入值。 AssemblyScript編譯器會將這些轉變爲WebAssembly模塊。
so,你如今徹底能夠在不學習一門新語言的狀況下,你就可以去寫WebAssembly,並從中獲益而且可以利用全部WebAssembly所能提供給你的好處,這是很是強大的。
有些事情須要你記住,WebAssembly並不像TypeScript那樣具備垃圾回收功能,至少如今尚未。 Deepti以後會關於這個進一步討論。 至少目前而言,你須要本身作內存管理
因此AssemblyScript提供給咱們一系列的內存管理模塊。你只須要將它們從倉庫里拉下來,而後用這些C語言風格的代碼對它們進行內存分配管理 這是咱們目前須要去習慣的,但它確實十分有用。一旦WebAssembly支持垃圾回收,它會變得更好AssemblyScript已經徹底開源,但它仍是一個處於起步階段的小項目 背後有許許多多充滿激情的人在爲它做支持 儘管它已經有了幾個贊助商,但仍是比不上像有Mozilla在背後作支持的Rust或Emscripten。
全部人都說這是確定有用,而且體驗感很好。
個人同事Arron Turnner用AssemblyScript寫了一套完整的模擬器
若是你由於使用它感到心累,那麼你能夠在GitHub上看他是如何寫這個代碼的。
在這裏,我想向各位明確的是,目前而言,將全部的東西都編譯爲wasm並非一個明智的決定 JavaScript和WebAssembly並非競爭對手,相反它們更應該是合做關係。在一塊兒使用它們的同時,並不會將對方所取代 好比調試webassembly會變得更難。還有在對webassembly代碼作code split(代碼拆分)的時候,會比javascript更加困難
你必須來回調用函數,這並非一個很好的體驗 已經有很多人在推特告訴我說,他們想用C++來編寫他們的Web組件
我不知道爲何他們想這麼作,若是他們真的想這麼作,我也不推薦。 我想說一些適合WebAssembly來作的一些事,好比作一些性能審查,測量你的性能瓶頸在哪裏,看看WebAssembly是否能夠幫助你。若是你有發現平臺上的空白,你能夠用其餘語言來彌補它。 再次強調,WebAssembly只是你的工具。歡迎加羣和咱們交流
若是感興趣能夠關注咱們的微信公衆號