WebAssembly學習筆記

WebAssembly是最近十年 web 技術發展中最重大的一個新技術。不少人可能都據說過它最重要的一個特性:性能好,運行快。那WebAssembly到底是什麼?是什麼使得它性能好運行快的呢?web

WebAssembly是什麼?

WebAssembly 是一種能把除了JavaScript之外的編程語言編寫的代碼通過編譯器編譯轉換爲能在現代瀏覽器中運行的代碼的技術。衆所周知,JavaScript在 Web 中的地位一直獨步天下,無 yan 能敵,因此WebAssembly所指的性能優點,是針對 JavaScript 而言的。WebAssembly並非爲了替代 JavaScript 出現的,而是但願與 JavaScript 並駕齊驅共同開發出性能更高的應用。編程

首先看看 JavaScript 的性能歷史

JavaScript誕生於1995年,目的是爲了給瀏覽器 HTML 網頁增長動態交互功能,並無考慮太多性能問題,事實證實在前十年裏瀏覽器也不須要它有多快。一切變化發生在2005年,谷歌在多款交互應用中使用Ajax技術讓交互體驗獲得了極大的提高,讓人們認識到了原來網頁能作的事情遠遠不是內容的展現和表單的提交。瀏覽器

到2008年,JavaScript在瀏覽器中低下的執行效率,已經成爲限制程序猿們在網頁施展拳腳的一大阻礙。忽然,有個叫谷歌的廠商推出了一款叫Chrome的瀏覽器,它與以往瀏覽器最大的不一樣在於內置了一個 JITs(just-in-time compilers),一個能在 js 代碼執行時根據某些模式動態編譯代碼爲能在瀏覽器中更高效執行的代碼的技術,詳細介紹能夠看這篇文章: a crash course in just in time(jit) compilers。今後拉開了瀏覽器性能大戰的序幕。服務器

js performanc

時間再推動10年到2018年,此時JavaScript的使用場景已經遠遠超過了原先的想象:服務端、網頁遊戲、WebVR/AR、圖片/視頻處理等等場景,JITs 都已經不能知足這些對性能日益嚴苛的場景了,此時咱們須要更進一步的突破,這個就是 WebAssembly網絡

爲何WebAssembly更快?

就如第一部分所提,WebAssembly的性能優點是針對 JavaScript 而言的,下面咱們分別從 JavaScript 和 WebAssembly 的執行過程一一對比優點到底在哪:編程語言

js-wb-excute

獲取

因爲 WebAssembly 是由編譯器生產出來的,而且將被瀏覽器直接解析執行,能夠節省那些爲了給人類閱讀而添加的沒必要要代碼,從而能夠作到文件大小甚至比通過壓縮的 JS 代碼更小。因此在相同的網絡狀況下,從服務器獲取一個 WB 文件會比獲取一個 JS 文件 更快。函數

解析

當 JS 文件成功到達瀏覽器以後,瀏覽器會將其解析成一棵抽象語法樹(Abstract Syntax Tree)(可是隻會先解析當前須要執行的那部分代碼,而其他未執行的函數將會保存成存根),而後再轉換爲 JS 引擎識別的 IR(intermediate representation) 層字節碼(認識 JAVA 的應該對這個詞不陌生)。性能

反過來咱們看 WebAssembly 自己已是通過高級語言編譯出來的 IR 層代碼了,不須要在瀏覽器端進行解析而只須要把通過壓縮的內容解碼出來,節省了至關多的時間。優化

編譯和優化

這個階段是 JITs 負責作的事情,不一樣瀏覽器對 WebAssembly 的處理可能會有細微差異,咱們以都使用 JITs 進行優化的場景來看看爲什麼 WebAssembly 會比 JavaScript 更快,有如下三點: (閱讀下面內容須要先對 JIT 有必定認識,不清楚的能夠先看 這裏編碼

  1. 因爲 WebAssembly 的輸入類型是固定的(byte),因此不須要經過運行代碼這種方式去檢查輸入類型來進行編譯優化
  2. 在 JavaScript 中相同一段代碼可能由於輸入值不一樣須要分別編譯成不一樣的版本,而 WebAssembly 也不須要進行這種冗餘的操做,緣由如上; 三、 WebAssembly 在從高級語言(C/C++/Rust)編譯而來的時候,已經通過編譯器優化一次了,因此在 JITs 中須要作的事情更少;

重優化

仍是因爲 JavaScript 動態類型的緣由,一段通過了深度優化的代碼,可能由於此次執行的時候輸入值類型變了,致使 JITs 須要根據輸入值類型從新進行一次上一步的優化工做,這也須要花費必定的時間。

而 WebAssembly 輸入值固定,JITs 不須要在每次代碼執行時去計算輸入值的類型,從而不會發生重優化這樣的事情。

執行

JavaScript 代碼通常是人寫的,而 WebAssembly 是由編譯器編譯出來的,是直接針對機器產生的代碼,會包含更多對機器性能優異的指令(instructions),這部分差別針對不一樣的功能代碼 WebAssembly 可能會比 JavaScript 快 10%~800%

垃圾回收

咱們都知道在 JavaScript 中沒必要人工去執行變量的釋放和內存的回收,由於 JS 引擎有自動垃圾回收功能,能自行判斷該回收什麼東西甚至足夠智能知道在什麼時候進行回收操做。可是這仍是存在天花板可能會影響代碼的執行。

在目前爲止,WebAssembly 都不支持自動垃圾回收,內存由代碼手動管理(因爲使用了 C/C++編寫),這將會加大開發者編碼的難度,但能保證代碼性能更可控。

總結

總的來講,大多數場景下 WebAssembly 比 JavaScript 性能更好是由於:

  1. WebAssembly 代碼更小的體積;
  2. 解碼 WebAssembly 比解析轉譯 JavaScript 用的時間更少;
  3. 優化 WebAssembly 的用時比優化 JavaScript 的更短,由於前者是已經通過一次編譯優化而且面向機器的代碼;
  4. WebAssembly 沒有重優化這個過程;
  5. WebAssembly 包含對機器更友好的指令;
  6. JavaScript 沒法人爲控制垃圾回收,而 WebAssembly 能夠有效控制內存回收的時機;

=============

本文主要知識和靈感來源於:

  1. A cartoon intro to WebAssembly系列文章,感謝做者。後續本博客會翻譯幾篇此做者編寫的 WebAssembly 使用教程。
  2. WebAssembly Concepts
  3. WebAssembly format

版權聲明:原創文章,如需轉載,請註明出處「本文首發於xlaoyu.info

相關文章
相關標籤/搜索