F7.12.1Main-thread contention from motion设计研究
动效计算与渲染占用的资源可能挤占主线程导致卡顿
别名: 主线程争用 · 动画卡顿 · 布局抖动
概念解释
动效的插值、布局和绘制如果挤在主线程上,输入处理和下一帧会一起错过垂直同步。卡顿来自主线程争用,不是时长设长了。一段 200 毫秒的运动,每帧若在主线程上做布局,16 毫秒的帧预算被吃光,手指滚动和点击回调一起排队。jank 是这条账,和「过渡在知觉上要播多久」分开记。
机制
常见的界面线程既跑脚本、又算样式和布局、又派发输入。动画若每帧改会触发重排的属性(宽高、边距、文档流里的位置),整棵子树在每一帧重新布局,工作量随节点数涨。合成器本来可以只挪图层,但这条路要求运动停留在变换和不透明度上;一旦掉回布局,主线程和渲染锁在一起。
争用的可见结果不是「动画变慢」,而是帧时间出现长尾:多数帧还行,个别帧 40、70 毫秒,运动变得一顿一顿。输入事件若也在同一线程,卡顿帧里的点击会延迟到下一帧才处理,跟手性一起坏。
怎么研究
用帧时间直方图,而不是平均帧率。自变量:动画属性是否触发布局、同时是否有输入、节点数量。因变量:超过帧预算的帧占比、输入到处理的延迟、长尾(例如 95 分位帧时间)。必须在目标设备上录,模拟器的主线程形状不一样。
报告是否在滚动中触发动画:滚动本身已占用布局,叠上去的运动更容易把预算打穿。
边界
- 纯合成器运动(图层变换)几乎不走这条争用,除非上传了过多图层或大面积模糊。
- 时长缩短减的是帧数,不减每帧工作量;短而重的运动照样打穿预算。
- 后台标签页被节流后,争用模式会变,不能用后台时的帧时间代表前台。
怎么落地
- 把会改文档流的属性从交互动画里拿掉;位移走变换。
- 动画期间避免额外的脚本布局读取,防止强制同步布局。
- 验证:在低端真机上打开帧时间图,一边滚一边播该运动。95 分位越过预算,就是主线程被挤占。