【JSConf EU 2018】Rust + WebAssembly

歐洲JSConf上的神祕項目

在今年的歐洲JSConf上來自Mozilla的Lin Clark爲咱們展現一個神祕項目,一個的拱形彩虹門(視頻傳送門),它其實是由三萬個彩色LED組成的畫布,能夠展示燈光動畫,而且經過Rust編寫的WebAssembly模塊來控制「拱門」的燈光動畫。Lin在2017年的JSConf上也曾作過關於WebAssembly的演講,在該演講中她提到2008年是JavaScript執行效率曲線的一個拐點,隨着衆多瀏覽器加入了JIT編譯器(Just-in-time compiler),JavaScript的運行性能帶來了十倍的增速,這爲JavaScript插上了一雙翅膀使它能夠自由翱翔在瀏覽器端、服務器端和客戶端。Lin指出WebAssembly的誕生可能會成爲曲線的下一個拐點。可見Mozilla對WebAssembly的重視程度。html

emm...讓咱們回到2018年。Lin在會上說明了如何使用WebAssembly模塊控制「拱門」的燈光動畫。下面讓咱們來看下這是如何作到的。web

用字節把空間或時間連續起來

咱們所處的空間是一個三維空間,若是再給它加上時間維度,那它就是四維空間。編程

計算機是沒有辦法理解這個四維空間的,若是要讓計算機能夠「理解」,咱們須要對四維空間降維。首先是時間維度,能夠經過幀來完成的。顯示屏就像一個翻頁的書,每一幀就至關於書的一頁。數組

在web端,60FPS是能夠經過屏幕流暢展現動畫的要求。這意味着你有60個不一樣的屏幕快照--一秒時間內60個點的動畫定格的樣子。能夠想象下一連串表明着三維空間的快照。瀏覽器

如今要從三維降到二維,咱們要作的是將空間壓平到一個方格紙上。服務器

如今已經降低到了二維,咱們須要再一次降維。把方格紙上面的每一行拿出來按順序鏈接起來。數據結構

如今降低到了一行像素,咱們已經能夠把它放到內存裏面了,由於WebAssembly內存(linear memory)基本就是一排小格子。這意味着咱們已經降低到一維結構,可是仍然擁有着表明着二維、三維或四維的所有數據。只是如今它們是以一種連續的、線性的方式在展現。app

線性內存(Linear memory)

線性內存是JavaScript和WebAssembly的一個主要通訊方式,WebAssembly和運行它的JavaScript均可以訪問這個對象。線性內存其實是一個可變大小的ArrayBuffer對象,本質上是連續的、按字節可尋址的一段內存。編程語言

爲了使上面提到的「拱門」產生燈光動畫,JavaScript告訴WebAssembly模塊:「好的,如今就填入動畫。」,這一步經過JavaScript調用WebAssembly的function來完成。函數

經過WebAssembly爲線性內存裏的每個像素填入顏色。

而後JavaScript代碼將獲取這些顏色數據並把他們轉化成一個JSON數組發送給「拱門」。

接下來咱們來看下如何在JavaScript裏使用這些數據。

爲線性內存填入顏色

線性內存實際上是一大行0和1。若是你想賦予這些0和1意義,那你須要指出如何分割它們。你要作的是爲AarryBuffer建立一個TypedArray,告訴JavaScript如何對AarryBuffer裏的比特位(bit)行分段。就像正在繪製的格子圍繞着這些比特位對它們說那些比特位是屬於那些數字。

例如你用了一個16進制的值,那你的數字將有24位的寬度。因此你須要一個24位的格子。每一個格子都包含一個像素,而可容納24位最小的格子是32位的(int32),因此咱們將在這個緩衝區上建立一個Int32Array的視圖。它將這段緩衝區的字節碼包裹到格子裏。在這個例子裏咱們須要添加一些空白來填充這個格子由24位補齊到32位。

若是咱們使用RGB值,這些格子將是8位的寬度。爲了獲得一個RGB的值,你將使用每三個格子表明你的R、G和B的值。這意味着你須要遍歷這些格子,並取出它們裏面的數字。

直接使用線性內存,你須要手動(寫一些代碼)遍歷它,把它裏面的數據取出來存放到更加合理的數據結構裏。對於這個項目來講,這樣作不是很糟糕。顏色的映射是數字,它們相對容易使用線性內存來表示。咱們使用的數據結構(RGB值)也不是很複雜。可是若是你使用的是更加複雜的數據結構,直接處理內存將會很痛苦。若是你能夠直接傳一個JavaScript對象給WebAssembly,讓WebAssembly去維護它,這將會變簡單不少。你只須要添加一個很小的庫(wasm-bindgen)就能夠作到這些。

使用wasm-bindgen

wasm-bindgen是使用Rust寫的一個庫,它可使JavaScript與WebAssembly模塊之間的數據交互變的更簡單。它用一個JavaScript wrapper 來包裹WebAssembly模塊。這個wrapper知道如何將複雜的JavaScript對象寫入線性內存。而後,當WebAssembly函數返回一個值時,JavaScript wrapper將從線性內存中獲取數據並將其從新轉換爲JavaScript對象。

要作到這一點,它會查看Rust代碼中的函數簽名,並計算出所需的JavaScript。這適用於像字符串這樣的內置類型,也適用於你定義在代碼裏的類型。wasm-bindgen將Rust結構體轉化JavaScript的類。該工具在當前版本只支持Rust,以後會不斷完善從而支持其餘編程語言(例如:C/C++)。

這個項目是開始學習WebAssembly的很好的開始,由於咱們能夠經過本身編寫的WebAssembly模塊來對真實世界產生影響。是否是很酷、頗有趣。想體驗經過寫WebAssembly模塊來控制燈光動畫的樂趣嗎?Mozilla已經幫咱們準備了在線環境The Arch,如今就開始體驗吧!

相關文章
相關標籤/搜索