配了三年性能优化,今天才发现页面卡从来不是代码的问题——Chrome 三年把输入这件事从根上修了
用户说「你这页面怎么卡卡的」,你把 Lighthouse 跑了一遍、INP 监控接了、主线程任务全部分片了,代码层面找不到任何问题。最后你只能说「可能用户网速慢」。
这个锅,有时候真不是代码的。
Chrome 团队花三年追这个 bug,发现问题根本不在渲染层——而在手指碰到屏幕的那一刻。2026 年,他们把这个输入管道彻底重写了,安卓端滚动卡顿频率直接降了 48%。
这件事叫 Input Vizard,是 Chrome 安卓性能架构里最底层的一次重构,普通人感知不到,但每个在移动端做产品的人都受益。
为什么代码没问题,滚动还是卡
先说清楚这个问题的本质。
60Hz 屏幕每 16.7ms 要出一帧。手指滑动时,Chrome 必须在这一帧里算出下一个滚动位置并画出来。如果超时,屏幕就只能重复显示上一帧——用户看到的就是「一卡一卡」。
这本来不是问题,普通安卓 app 把输入和渲染跑在同一个线程,没有中间商。但 Chrome 是多进程架构:浏览器进程、渲染进程、GPU 进程分开。手指事件从屏幕到渲染进程,要穿过好几层。
关键是,手指事件最初要经过主浏览器线程才转发——而这个线程通常正在忙着处理网页的 JS。哪怕只是跑一个 20ms 的小任务,恰好碰到手指事件来了,这次滚动就注定卡一帧。
所以问题从来不是「页面代码写得烂」,而是「输入事件被主线程堵在半路了」。
Input Vizard:让输入事件走专属通道
Chrome 团队用 Perfetto 自动化 trace 工具追踪了完整链路:从手指触碰屏幕,到新帧显示出来,一共经过多少个线程节点、每个节点耗时多少。
结果发现,手指事件要绕 3~4 个中间线程才能到达 GPU 合成器。其中任何一个节点延迟,都会导致帧超时。
解决方案很简单粗暴:让手指事件走专用通道,直接绕过主浏览器线程。
Input Vizard 把手指事件直接路由到 Viz 合成器线程,不再经过主浏览器进程。GPU 拿到手指坐标后自行计算滚动帧,不等渲染进程里的 JS 跑完。
这意味着,即使你的页面正在执行长任务,手指滑动依然能保持流畅——因为输入不再排队等 JS 了。
四个配套机制,缺一不可
Input Vizard 是核心,但它不是单独工作的。Chrome 同时部署了四个辅助机制,组成完整的输入管道优化:
Input Prediction(输入预测)
如果操作系统延迟交付手指事件,Chrome 会根据已记录的手指轨迹估算当前位置,生成「预帧」。等真实事件到达时再校正。这样即使 OS 慢一拍,滚动也不中断。
Input Framer(输入成帧)
Chromium 给浏览器留了约 5.5ms(60Hz 下刷新周期的 1/3)的缓冲窗口,等候迟到的手指事件。如果事件在窗口内到达,正常渲染;如果超时,则基于预测帧显示。这样减少「空帧」导致的卡顿,同时不牺牲响应性。
Direct2Thread(直连线程)
原本消息要从渲染进程经过 IO 线程、IPC 转发才能到 GPU 进程。Direct2Thread 消除了中间两个节点,直接在进程内线程之间传递输入信号,将跨进程通信延迟从数百微秒压缩到接近零。
Browser Controls in Viz(浏览器控件进 Viz)
地址栏、标签栏这类浏览器自带控件,以前跟网页内容不在同一个合成路径上——滑动时地址栏经常跟页面滚动「不同步」。把这部分 UI 也纳入 Viz 合成器后,浏览器控件和页面内容真正同步了,用户看到的就是一个整体流畅的界面。
48% 怎么测出来的
Chrome 团队没有用实验室数据。他们在真实用户的安卓设备上跑了三年的 A/B 测试,对比 2023 年和 2026 年的 jank 发生频率——结果差了 48%。
这个数字指的是「滚动中出现至少一帧超时的频率」,不是单帧延迟的平均值。频率降低 48% 意味着大多数用户的日常滑动体验都有了感知级别的改善。
但要注意:这个改进不影响页面加载速度,不影响 JS 执行时间,也不影响渲染管线的计算量。 它只解决滚动本身的帧到达率问题。
对前端工程师意味着什么
这个变化是透明的——Chrome 自动推送,不需要你改任何代码。
但理解它的逻辑有助于定位问题。当用户说「页面卡」,你排查完代码层面的 INP、LCP、CLS 之后,现在可以多想一层:有没有可能是浏览器自身的输入架构问题?
特别是:如果用户在低端安卓机上、在页面已经跑了大量 JS 之后滚动、卡顿是间歇性出现的但 Lighthouse 全绿——那这个锅,很可能就是旧版 Chrome 的输入管道问题,代码层面永远修不了。
Chrome 154 之后的版本会逐步把这一套架构稳定下来。未来移动端 Web 的流畅度天花板,会比现在高一截。
下一步你可以做的:
- 在真实低端安卓机上测试你的页面滚动流畅度(不是模拟器)
- 观察用户反馈里「卡」的描述:是首屏加载卡,还是交互过程中卡,还是滚动时卡——三种卡来源不同,解决方案也完全不同
- 如果你的页面大量依赖 scroll 事件做交互,考虑换成 Scroll-Driven Animation,把「滚动状态」的判定从 JS 搬到浏览器原生层,进一步减少主线程压力
评论区
登录后可评论。