F7.12.1Main-thread contention from motion设计研究

动效计算与渲染占用的资源可能挤占主线程导致卡顿

别名: 主线程争用 · 动画卡顿 · 布局抖动

概念解释

动效的插值、布局和绘制如果挤在主线程上,输入处理和下一帧会一起错过垂直同步。卡顿来自主线程争用,不是时长设长了。一段 200 毫秒的运动,每帧若在主线程上做布局,16 毫秒的帧预算被吃光,手指滚动和点击回调一起排队。jank 是这条账,和「过渡在知觉上要播多久」分开记。

机制

常见的界面线程既跑脚本、又算样式和布局、又派发输入。动画若每帧改会触发重排的属性(宽高、边距、文档流里的位置),整棵子树在每一帧重新布局,工作量随节点数涨。合成器本来可以只挪图层,但这条路要求运动停留在变换和不透明度上;一旦掉回布局,主线程和渲染锁在一起。

争用的可见结果不是「动画变慢」,而是帧时间出现长尾:多数帧还行,个别帧 40、70 毫秒,运动变得一顿一顿。输入事件若也在同一线程,卡顿帧里的点击会延迟到下一帧才处理,跟手性一起坏。

怎么研究

用帧时间直方图,而不是平均帧率。自变量:动画属性是否触发布局、同时是否有输入、节点数量。因变量:超过帧预算的帧占比、输入到处理的延迟、长尾(例如 95 分位帧时间)。必须在目标设备上录,模拟器的主线程形状不一样。

报告是否在滚动中触发动画:滚动本身已占用布局,叠上去的运动更容易把预算打穿。

边界

  • 纯合成器运动(图层变换)几乎不走这条争用,除非上传了过多图层或大面积模糊。
  • 时长缩短减的是帧数,不减每帧工作量;短而重的运动照样打穿预算。
  • 后台标签页被节流后,争用模式会变,不能用后台时的帧时间代表前台。

怎么落地

  • 把会改文档流的属性从交互动画里拿掉;位移走变换。
  • 动画期间避免额外的脚本布局读取,防止强制同步布局。
  • 验证:在低端真机上打开帧时间图,一边滚一边播该运动。95 分位越过预算,就是主线程被挤占。

延伸

  • 同组F7.12.2 掉帧的动效比没有动效更损害体验,因为暴露了系统吃力 · F7.12.3 复杂动效在低端设备上需要降级或关闭而非等比缩放 · F7.12.4 同时触发的多个动效会叠加性能开销超出单个动效评估范围
  • 相邻R3.08 动画的性能开销 · R3.05 渲染阻塞与布局抖动 · F7.02 动效时长
  • 站内检索jank · frame budget · main thread

同组卡片

快捷操作

分享

分享当前页面

ios_share

https://hci.top/zh/handbook/F7.12.1