Chromium博客:引入共享内存版本控制技术改善缓慢交互
在Chrome团队,我们认为大多数时候快是不够的,我们必须始终保持快速。今天的《The Fast and the Curious》文章探讨了我们如何通过调查Chrome在所有网站上响应用户交互的现场数据来贡献Core Web Vitals,最终提升了网络性能。
随着每天数十亿人通过网络完成任务,浏览器负责同时托管多个应用程序的责任越来越大,资源争用成为一个挑战。多进程Chrome浏览器需要竞争多种资源:当然是CPU和内存,还有其内部服务之间的工作队列(本文中指的是网络服务)。
这就是为什么我们一直专注于识别和修复Chrome用户现场数据中的缓慢交互,这些数据是真实用户体验的权威来源。我们通过在Chrome Canary上记录匿名的Perfetto跟踪来收集这些现场数据,并使用保护隐私的过滤器进行报告。
在查看缓慢交互的现场数据时,一个特别的原因引起了我们的注意:反复同步调用从网络服务获取当前网站的Cookie。
让我们深入了解一些历史。
发展中的网络与Cookie
Cookie从网络平台诞生之初就是其中的一部分。它们通常是这样创建的:
|
|
之后这样检索:
|
|
在单进程浏览器中,它的实现很简单,将Cookie jar保存在内存中。
随着时间的推移,浏览器变成了多进程,托管Cookie jar的进程负责回答越来越多的查询。然而,由于Web规范要求Javascript同步获取Cookie,因此回答每个document.cookie查询是一个阻塞操作。
操作本身非常快,所以这种方法通常没问题,但在多个网站从网络服务请求Cookie(和其他资源)的高负载场景下,请求队列可能会积压。
我们通过缓慢交互的现场跟踪发现,一些网站触发了低效场景,连续多次获取Cookie。我们增加了额外的指标来衡量在所有导航中GetCookieString() IPC冗余(返回值与上次相同)的频率。我们惊讶地发现87%的Cookie访问是冗余的,并且在某些情况下,这可能每秒发生数百次。
document.cookie的简单设计适得其反,因为网络上的Javascript像使用本地值一样使用它,而实际上它是一个远程查找。这是一个经典的计算机科学缓存案例吗?没那么简单!
网络规范允许协作域修改彼此的Cookie。因此,每个渲染器进程的简单缓存不起作用,因为它会阻止此类站点之间的写入传播(导致过时的Cookie,例如,在电子商务应用程序中购物车不同步)。
新范式:共享内存版本控制
我们通过一个新范式解决了这个问题,我们称之为共享内存版本控制。其思想是,现在每个document.cookie值都与一个单调递增的版本配对。每个渲染器缓存其最后读取的document.cookie以及该版本。网络服务在共享内存中托管每个document.cookie的版本。因此,渲染器可以判断它们是否拥有最新版本,而无需向网络服务发送进程间查询。这将与Cookie相关的进程间消息减少了80%,并使document.cookie访问速度提高了60% 🥳。
假设检验
改进算法很好,但我们最终关心的是这种改进是否能为用户改善缓慢交互。换句话说,我们需要检验停滞的Cookie查询是缓慢交互的重要原因这一假设。
为了实现这一点,我们使用Chrome的A/B测试框架研究效果,并确定它与其他减少资源争用的改进相结合,将所有平台上最慢的交互改善了约5%。这进一步导致更多网站通过Core Web Vitals 🥳。所有这些加起来为用户带来了更无缝的网络体验。
随着这项技术向1%用户(11月)、50%用户(12月)以及所有用户(2月)发布,网络上Chrome最慢交互的加权平均时间线。
迈向无缝网络!
作者:Gabriel Charette、Olivier Li Shing Tat-Dupuis、Carlos Caballero Grolimund和François Doray,来自Chrome工程团队。