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
详细解读
WebAssembly Reference Types
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 | Chrome 95 | WebAssembly Exception Handling |
2021-11-16 | Chrome 96 | WebAssembly Reference Types |
Chrome今年所支持的WebAssembly特性,都是非常关键的,这将进一步促进WebAssembly的应用。
近期,Photoshop近期发布了其Web应用,也是通过将C++编译为WebAssembly来实现的,其中WebAssembly Exception Handling与WebAssembly SIMD发挥了重要的作用。
图片来源:Photoshop's journey to the web
对WebAssembly感兴趣的同学,欢迎阅读我的博客《十年磨一剑,WebAssembly是如何诞生的?》,了解WebAssembly的发展历史。
HTTPS DNS records
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站点:
图片来源:Firefox 83 introduces HTTPS-Only Mode
Chrome 94已经支持用户配置HTTPS-First Mode,未来可能会默认开启。虽然名字不一样,实际效果与Firefox的HTTS-Only Mode差不多。
Priority Hints
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:
图片来源:Optimizing resource loading with Priority Hints
从视频可以很明显得看出来,背景图片的加载明显提前了,用户所感知的体验提升了很多:
视频来源:Optimizing resource loading with Priority Hints
Priority Hints为WICG提案,由Google的开发者负责,目前并未得到其他浏览器的支持。
WebAssembly Dynamic Tiering
Chrome 96开始试用WebAssembly Dynamic Tiering,目的是优化WebAssembly的编译过程,改变了之前贪婪的编译方式,以降低对资源的浪费。
这个特性纯粹是V8引擎层面的优化,与应用层开发者没啥关系,不过还挺有意思的,值得了解一下。
V8引擎中有两个编译器用来编译WebAssembly,分别是Liftoff和TurboFan,前者是基础编译器,后者是优化编译器。
Liftoff是one-pass compiler,它只会读取一遍WebAssembly代码,然后直接生成机器代码,这样提高了编译速度,节省了启动时间。不过Liftoff编译的机器代码没有经过太多优化,因此执行性能相对差一些。
图片来源:Liftoff: a new baseline compiler for WebAssembly in V8
TurboFan是multi-pass compiler,同时负责WebAssembly和JavaScript的优化编译,它会应用各种方法优化所生成的机器代码,例如优化寄存器的分配。因此TurboFan所生成的机器代码更加高效,不过编译时间更长。
图片来源:Launching Ignition and TurboFan
TurboFan的编译过程远比Liftoff复杂(天下没有免费的午餐),如下图所示:图片来源:Liftoff: a new baseline compiler for WebAssembly in V8
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」