我們如何使用 WebAssembly 將 Web 應用程式加速 20 倍

我們如何使用 WebAssembly 將 Web 應用程式加速 20 倍

本文討論透過使用 WebAssembly 取代 JavaScript 計算來加速瀏覽器應用程式的案例。

WebAssembly - 它是什麼?

簡而言之,這是基於堆疊的虛擬機器的二進位指令格式。 Wasm(簡稱)通常被稱為程式語言,但事實並非如此。 指令格式與 JavaScript 一起在瀏覽器中執行。

重要的是,WebAssembly 可以透過 C/C++、Rust、Go 等語言編譯原始碼來取得。 這裡使用統計類型和所謂的平面記憶體模型。 如上所述,程式碼以緊湊的二進位格式存儲,使其幾乎與使用命令列運行應用程式一樣快。 這些功能導致了 WebAssembly 的普及。

提醒: 對於“Habr”的所有讀者 - 使用“Habr”促銷代碼註冊任何 Skillbox 課程可享受 10 盧布的折扣。

技能箱推薦: 實踐課程 “移動開發者專業版”.

目前,Wasm 用於許多應用程序,從 Doom 3 等遊戲到 Autocad 和 Figma 等 Web 移植應用程式。 Wasm 也用於無伺服器運算等領域。

本文提供了使用 Wasm 加速分析 Web 服務的範例。 為了清楚起見,我們採用了一個用 C 編寫的工作應用程序,該應用程式被編譯為 WebAssembly。 結果將用於替換 JS 中表現不佳的部分。

應用改造

此範例將使用 fastq.bio 瀏覽器服務,該服務面向遺傳學家。 該工具可讓您評估 DNA 定序(解密)的品質。

以下是應用程式實際運行的範例:

我們如何使用 WebAssembly 將 Web 應用程式加速 20 倍

這個過程的細節不值得深究,因為對於非專業人士來說相當複雜,但簡而言之,科學家可以透過上面的資訊圖表來了解DNA定序過程是否順利以及出現了哪些問題。

該服務有替代方案:桌面程式。 但 fastq.bio 允許您透過視覺化資料來加快工作速度。 在大多數其他情況下,您需要能夠使用命令列,但並非所有遺傳學家都具備必要的經驗。

一切都很簡單。 輸入是以文字檔案呈現的資料。 該文件是由專門的測序工具產生的。 該文件包含 DNA 序列列表和每個核苷酸的質量分數。 檔案格式為 .fastq,這就是該服務得名的原因。

JavaScript 中的實作

使用者使用 fastq.bio 時的第一步是選擇適當的文件。 使用 File 對象,應用程式從檔案中讀取隨機資料樣本並處理該批次。 JavaScript 的工作是執行簡單的字串操作並計算指標。 其中之一是不同 DNA 片段上核苷酸 A、C、G 和 T 的數量。

計算出必要的指標後,使用 Plotly.js 將它們視覺化,並且該服務開始使用新的資料樣本。 進行分塊是為了提高使用者體驗的品質。 如果您同時處理所有數據,該過程將凍結一段時間,因為包含排序結果的檔案佔用數百 GB 的檔案空間。 該服務獲取大小從 0,5 到 1 MB 的資料片段,並逐步處理它們,建立圖形資料。

以下是它的工作原理:

我們如何使用 WebAssembly 將 Web 應用程式加速 20 倍

紅色矩形包含用於獲得可視化的字串轉換演算法。 這是該服務中計算量最大的部分。 值得嘗試用 Wasm 取代它。

測試 WebAssembly

為了評估使用 Wasm 的可能性,專案團隊開始尋找現成的解決方案,以基於 fastq 檔案建立 QC 指標(QC - 品質控制)。 在用 C、C++ 或 Rust 編寫的工具中進行搜索,以便可以將程式碼移植到 WebAssembly。 此外,該工具不應該是「原始的」;需要已經經過科學家測試的服務。

結果,做出了有利於 序列。 該應用程式非常流行,它是開源的,來源語言是C。

在轉換為 Wasm 之前,有必要先了解桌面版 seqtk 的編譯原理。 根據 Makefile,這就是您需要的:

# Compile to binary
$ gcc seqtk.c 
   -o seqtk 
   -O2 
   -lm 
   -lz

原則上,您可以使用 Emscripten 編譯 seqtk。 如果不存在,我們就湊合一下。 Docker映像.

$ docker pull robertaboukhalil/emsdk:1.38.26
$ docker run -dt --name wasm-seqtk robertaboukhalil/emsdk:1.38.26

如果需要 您可以自己組裝,但這需要時間。

在容器內,您可以輕鬆使用 emcc 作為 gcc 的替代品:

# Compile to WebAssembly
$ emcc seqtk.c 
    -o seqtk.js 
    -O2 
    -lm 
    -s USE_ZLIB=1 
    -s FORCE_FILESYSTEM=1

最小變化:

Emscripten 使用 .wasm 和 .js 來產生文件,而不是輸出到二進位文件,這些文件用於運行 WebAssemby 模組。

USE_ZLIB 標誌用於支援 zlib 函式庫。 該庫已分發並移植到 WebAssembly,Emscripten 將其包含在專案中。

Emscrippten 虛擬檔案系統已啟動。 這 類 POSIX FS,在瀏覽器內的 RAM 中運作。 當頁面刷新時,記憶體被清除。

要理解為什麼需要虛擬檔案系統,有必要將從命令列執行 seqtk 的方式與執行已編譯的 WebAssembly 模組的方式進行比較。

# On the command line
$ ./seqtk fqchk data.fastq
 
# In the browser console
> Module.callMain(["fqchk", "data.fastq"])

獲得對虛擬檔案系統的存取是必要的,以免為字串而不是檔案輸入重寫 seqtk。 在這種情況下,資料片段在虛擬 FS 中顯示為 data.fastq 文件,並呼叫 main() seqtk。

這是新的架構:

我們如何使用 WebAssembly 將 Web 應用程式加速 20 倍

該圖顯示,不是在主瀏覽器執行緒中進行計算, 網路工作者。 此方法允許您在後台執行緒中執行計算,而不影響瀏覽器回應能力。 好吧,WebWorker 控制器啟動 Worker,管理它與主執行緒的互動。

seqtk 指令是使用 Worker 在已安裝的檔案上執行的。 執行完成後,Worker 會以 Promise 的形式產生結果。 當主執行緒收到訊息時,結果將用於更新圖。 如此反覆多次。

WebAssembly 效能如何?

為了評估效能的變化,專案團隊使用了每秒讀取操作數參數。 由於兩種實作都使用 JavaScript,因此不考慮建立互動式圖表所需的時間。

使用開箱即用的解決方案時,效能提高了九倍。

我們如何使用 WebAssembly 將 Web 應用程式加速 20 倍

這是一個非常好的結果,但事實證明,它還有優化的機會。 事實是大量的QC分析結果並沒有被seqtk使用,因此可以將其刪除。 如果這樣做,結果比 JS 提高了 13 倍。

我們如何使用 WebAssembly 將 Web 應用程式加速 20 倍

它是透過簡單地註解掉 printf() 指令來實現的。

但這還不是全部。 事實是,在這個階段,fastq.bio透過呼叫不同的C函數來接收分析結果,每個函數計算自己的一組特徵,從而使檔案的每個片段被讀取兩次。

為了解決這個問題,決定將兩個功能合而為一。 結果,生產力提高了 20 倍。

我們如何使用 WebAssembly 將 Web 應用程式加速 20 倍

值得注意的是,如此出色的成績並不總是能夠取得。 在某些情況下,效能會下降,因此值得評估每種情況。

作為結論,我們可以說 Wasm 確實提供了提高應用程式效能的機會,但您需要明智地使用它。

技能箱推薦:

來源: www.habr.com

添加評論