天天看點

Chrome 96 支援 WebAssembly 引用類型了!

11月16日正式釋出的Chrome 96,帶來了哪些新特性呢?

TL;TR

  • Chrome 96最大的亮點是什麼?這一次的主角依然是WebAssembly,它有了引用類型!
  • Chrome 96是哪天釋出的?2021-11-16
  • Chrome 96更新了多少個特性?一共20個特性,其中12個新特性,4個試用特性,3個開發特性,1個廢棄特性,具體有哪些特性可以檢視Chrome Platform Status
  • Chrome 96将使用哪個版本的V8引擎?v9.6
  • 我感興趣的正式特性有哪些?
    • WebAssembly Reference Types
    • HTTPS DNS records
  • 我感興趣的試用(origin trial)特性有哪些?
    • Priority Hints
    • WebAssembly Dynamic Tiering

詳細解讀

Chrome 96正式釋出了WebAssembly Reference Types,Reference Types即引用類型,用externref關鍵詞表示。

之前,WebAssembly僅支援32位及64位的整數和浮點數,這樣使得處理複雜資料比如String和Object時非常麻煩。

以字元串為例,如果我們需要從JavaScript傳入一個字元串給WebAssembly函數使用,則需要這樣處理:

  • 将字元串轉換為整數(使用TextEncoder即可)
  • 将整數寫入WebAssembly的記憶體空間(WebAssembly的記憶體空間是一個線性的數組空間)
  • 将整數數組的位址傳給WebAssembly函數

雖然這些步驟由編譯工具比如wasm-bindgen來處理,我們不需要操心,但是這樣做會生成大量膠水代碼,損耗了編譯和執行性能。

支援Reference Types之後,WebAssembly也可以愉快地處理整數及浮點數之外的資料類型了。

WebAssembly/reference-types提案已經被納入WebAssembly标準,Firefox和Safari之前已經支援了。WebAssembly Reference Types使得其他WebAssembly提案成為可能,例如GC(Garbage collection)、Interface Types以及type Imports等。

WebAssembly/reference-types提案的負責人是Andreas Rossberg,他是Google前員工,參與了WebAssembly最初的設計,現在是WebAssembly核心規範的編輯。除了Reference Types,Andreas Rossberg還負責了WebAssembly的很多其他非常重要的提案,比如GC(Garbage collection)、Type Imports、Tail call等。

我在Chrome 91(

《Chrome 91支援WebAssembly SIMD,加速Web在AI等領域的應用》

)以及

Chrome 95

《Chrome 95終于支援WebAssembly異常處理了》

)部落格中分别介紹過WebAssembly SIMD與WebAssembly Exception Handling,可見,WebAssembly的能力正在變得越來越強大:

「時間」 「Chrome版本」 「特性」
2021-05-25 Chrome 91 WebAssembly SIMD
2021-10-19 WebAssembly Exception Handling
2021-11-16 Chrome 96

Chrome今年所支援的WebAssembly特性,都是非常關鍵的,這将進一步促進WebAssembly的應用。

近期,Photoshop近期釋出了其Web應用,也是通過将C++編譯為WebAssembly來實作的,其中WebAssembly Exception Handling與WebAssembly SIMD發揮了重要的作用。

Chrome 96 支援 WebAssembly 引用類型了!

圖檔來源:Photoshop's journey to the web

對WebAssembly感興趣的同學,歡迎閱讀我的部落格

《十年磨一劍,WebAssembly是如何誕生的?》

,了解WebAssembly的發展曆史。

Chrome 96正式支援了HTTPS DNS records,對于部署了HTTPS DNS records的網站,Chrome将始終使用HTTPS進行連接配接。

HTTPS DNS records是DNS的新特性,支援在DNS記錄中傳回除了網站的IP位址之外的一些額外的資訊:比如是否支援HTTPS,是否支援HTTP/2以及HTTP/3。

例如,下面的DNS記錄表示example.com支援HTTPS,并且支援HTTP/2和HTTP/3:

example.com 3600 IN HTTPS 1 . alpn=”h3,h2”      

這樣的話,浏覽器第一次通路example.com時,可以直接使用HTTPS進行連接配接。

否則,浏覽器不确定example.com是否支援HTTPS,隻能先使用HTTP進行連接配接,若服務端要求重定向到HTTPS,再使用HTTPS進行連接配接。這樣既耗費了1次多餘的連接配接,同時也不安全。

HTTPS DNS records對應的IETF提案為Service binding and parameter specification via the DNS (DNS SVCB and HTTPS RRs),目前尚未成為IETF正式的RFC,不過已經基本穩定了。

其實,從Chrome 91開始,Chrome預設使用HTTPS進行連接配接,這樣對于支援HTTPS的站點,第一次請求已經不是HTTP了,關于這個特性的介紹詳見我的

Chrome 90

部落格。該特性原計劃Chrome 90釋出,後來因為BUG推遲到了Chrome 91。

預設使用HTTPS協定,也是個不錯的方法,正經網站誰還用HTTP啊!不過有了HTTPS DNS records更好,浏覽器不用再去試錯了。

Chrome的核心原則為4S,其中之一為Security(另外3個S分别為Speed、Stability、Simplicity),是以Chrome對于推動HTTPS這件事一向非常執著。

Firefox 83在去年支援了HTTS-Only Mode,"禁止"使用者訪非HTTPS站點:

Chrome 96 支援 WebAssembly 引用類型了!

圖檔來源:Firefox 83 introduces HTTPS-Only Mode

Chrome 94已經支援使用者配置HTTPS-First Mode,未來可能會預設開啟。雖然名字不一樣,實際效果與Firefox的HTTS-Only Mode差不多。

Chrome 96開始試用Priority Hints,用于指定頁面資源的加載優先級,即importance屬性,幫助浏覽器根據優先級優化加載順序,進而優化頁面加載體驗。

浏覽器下載下傳頁面資源的順序由衆多因素所決定,比如資源的類型、位置及順序、是否在可視視窗、是否指定defer、async、preload等。浏覽器根據規則确定資源的優先級,進而确定下載下傳順序。

一般來講,浏覽器可以很好地決定資源下載下傳順序,但是由于缺乏對具體應用及具體頁面的深入了解,浏覽器下載下傳資源的順序很難是最優的。這時,如果我們就可以利用規則來調整資源的優先級,進而影響下載下傳順序,比如為頁面統計/監控腳本指定async。不過這種方法有點隔山打牛的感覺,既複雜又不一定能達到效果。

Priority Hints則非常簡單直接,通過important屬性指定資源的優先級,其取值為high、low、auto,其中auto為預設值,使用方式如下:

<!-- 通過important屬性指定圖檔的優先級 -->
<img src="/images/test.png" importance="high" />
<!-- 使用fetch的時指定優先級 -->
<script>
  fetch("https://example.com/", { importance: "low" }).then((data) => {});
</script>      

不過,importance屬性作為浏覽器确定資源加載順序的重要參考,但是并不具備決定性左右。

如下圖所示,通過使用Priority Hints提高背景圖檔的下載下傳優先級,Google Flight将Largest Contentful Paint(簡稱LCP,即最大内容繪制)從2.6s降低到了1.9s:

Chrome 96 支援 WebAssembly 引用類型了!

圖檔來源:Optimizing resource loading with Priority Hints

從視訊可以很明顯得看出來,背景圖檔的加載明顯提前了,使用者所感覺的體驗提升了很多:

Chrome 96 支援 WebAssembly 引用類型了!

視訊來源:Optimizing resource loading with Priority Hints

Priority Hints為WICG提案,由Google的開發者負責,目前并未得到其他浏覽器的支援。

Chrome 96開始試用WebAssembly Dynamic Tiering,目的是優化WebAssembly的編譯過程,改變了之前貪婪的編譯方式,以降低對資源的浪費。

這個特性純粹是V8引擎層面的優化,與應用層開發者沒啥關系,不過還挺有意思的,值得了解一下。

V8引擎中有兩個編譯器用來編譯WebAssembly,分别是Liftoff和TurboFan,前者是基礎編譯器,後者是優化編譯器。

Liftoff是one-pass compiler,它隻會讀取一遍WebAssembly代碼,然後直接生成機器代碼,這樣提高了編譯速度,節省了啟動時間。不過Liftoff編譯的機器代碼沒有經過太多優化,是以執行性能相對差一些。

Chrome 96 支援 WebAssembly 引用類型了!

圖檔來源:Liftoff: a new baseline compiler for WebAssembly in V8

TurboFan是multi-pass compiler,同時負責WebAssembly和JavaScript的優化編譯,它會應用各種方法優化所生成的機器代碼,例如優化寄存器的配置設定。是以TurboFan所生成的機器代碼更加高效,不過編譯時間更長。

Chrome 96 支援 WebAssembly 引用類型了!

圖檔來源:Launching Ignition and TurboFan

TurboFan的編譯過程遠比Liftoff複雜(天下沒有免費的午餐),如下圖所示:

Chrome 96 支援 WebAssembly 引用類型了!

V8引擎之前編譯WebAssembly的政策是這樣的:

  • 先使用Liftoff編譯WebAssembly代碼,編譯完成之後就可以執行了,同時立即使用TurboFan(背景線程)将所有WebAssembly的函數重新編譯一遍。
  • 每當TurboFan編譯完一個WebAssembly函數,則替換掉Liftoff的編譯結果,這樣當調用該函數時,執行的是經過TurboFan優化編譯的機器代碼。

這樣的編譯方式還是挺巧妙的,既提高了啟動速度,也保障了執行速度。不過,使用TurboFan将所有WebAssembly函數重新編譯一遍的做法,着實有些浪費CPU和記憶體,比較費電,不符合碳中和的時代背景:

  • 有的WebAssembly函數(如果不是大部分的話)根本不會被調用,為愛編譯?
  • TurboFan不使用主線程,不過還是會浪費worker線程的CPU以及記憶體。
  • TurboFan編譯所有函數的話,則有可能會耽誤對重要函數的編譯,反而降低了性能。

于是,V8計劃改變之前貪婪的編譯方式,引入Dynamic tiering技術,TurboFan隻編譯那些執行了多次的WebAssembly函數。

Dynamic tiering聽着很厲害的樣子,其實與V8引擎編譯JavaScript所使用的政策是相同的。對V8引擎如何編譯JavaScript感興趣的話,不妨閱讀我2年前的部落格

《V8引擎是如何工作的?》

既然編譯JavaScript時早就這麼幹了,那為啥V8不早點使用Dynamic tiering來優化WebAssembly編譯呢?核心原因目測是WebAssembly是靜态類型的,是以Liftoff編譯的機器代碼已經足夠快了,沒有JS那麼命苦,并不急着需要TurboFan的優化編譯。根據Liftoff: a new baseline compiler for WebAssembly in V8的測試結果,Liftoff編譯速度比TurboFan快了5~10倍,執行速度比TurboFan慢了18%~100%,使用之前的貪婪編譯政策問題也不大。

總結

這篇部落格介紹了4個Chrome新特性,拆解下來都會涉及比較基礎的知識點:DNS、HTTPS、HTTP、頁面加載過程、變量類型、編譯技術。是以,看起來我是在追逐最新的技術,其實我是在重溫那些最基礎的知識點。

所謂"溫故而知新",反過來也很有道理,"知新而溫故"。這也是我寫部落格最主要的目的,把寫作當成一種學習方法,通過輸出倒逼輸入。

另外,我從Chrome 94的部落格開始介紹試用(origin trial)特性,這樣既可以第一時間了解Chrome的最新特性,又可以給我更多的時間熟悉這些特性,當它們正式釋出的時候,我還是會把它們寫到新版本的部落格裡面,那時應該會有一些新的内容可以寫。

才疏學淺,我所寫的内容難免有錯誤之處,歡迎批評指正,個人微信:「KiwenLau」。

參考資料

  • Chrome 96 Beta: Conditional Focus, Priority Hints, and More
  • V8 release v9.6
  • 「Strings in WebAssembly (Wasm)」
  • Making WebAssembly better for Rust & for all languages
  • wast-binden: Support for Reference Types
  • WebAssembly Reference Types in Wasmtime
  • WebAssembly Reference Types Implemented in wasmtime, Lets Wasm Modules Handle Complex Types
  • 「Speeding up HTTPS and HTTP/3 negotiation with... DNS」
  • A safer default for navigation: HTTPS
  • Increasing HTTPS adoption
  • Firefox 83 introduces HTTPS-Only Mode
  • 「Optimizing resource loading with Priority Hints」
  • Largest Contentful Paint (LCP)
  • WebAssembly Dynamic Tiering ready to try in Chrome 96
  • WebAssembly compilation pipeline
  • 「Liftoff: a new baseline compiler for WebAssembly in V8」
  • 「Photoshop's journey to the web」