Skip to content

前端渲染优化

前提

了解屏幕刷新频率 HZ?丢帧?卡顿?

shell
# 1、关于屏幕刷新频率
大多数人屏幕的刷新率是 60Hz / 90Hz / 120Hz,代表着 1s 中,也就是 1000 ms 刷新多少次,其中的一次代表一帧
一帧的时间
   60Hz 1000/60 16.67ms
   90Hz 1000/90 11.11ms
   120Hz 1000/120 8.33ms
 60Hz 为例,页面中的内容变化就会开始渲染
   如果渲染的时间在一帧时间 16.67ms 以内,就会显得很流畅,
   如果渲染的事件 大于一帧 16.67ms,说面这一帧结束时页面还没变化完,这一帧的页面还是之前的内容,这个时间间隔越大,界面越卡,得过一段时间才能看到渲染的内容
问题来了,如果页面渲染很快 1ms 渲染完了,那么一帧 16.67ms 中的剩余 15 ms 用来干嘛?
   这个事件相当于主线程空闲事件,什么也不做,会触发 requestIdleCallback 函数,在渲染线程空闲的时候做事(优化) 
屏幕刷新率 Hz 这个值越高说明渲染效果越丝滑
   Hz 越小,说明每帧的时间间隔越小,如果页面渲染的很快,在 1ms/2ms/3ms 就渲染完了,那么帧越小,迎接下一针的变化极快,更显丝滑
 如果页面渲染的很慢,比如 100ms 才渲染完,那么表现上差不多

# 通俗理解
60帧/秒 = 每帧只有 16.6 毫秒
├─ JS 执行(宏任务+微任务)
├─ 样式计算
├─ 布局
├─ 绘制
└─ 合成

如果超过这个时间 丢帧 用户感知卡顿

# 一帧内没渲染完怎么办?会阻塞下一帧吗?
不会,画面继续显示上一帧已经渲染出的数据,当前帧会被丢弃,也就是丢帧,渲染这个操作则继续,屏幕刷新的间隔 16.6ms 是固定的
每隔一帧的时间继续执行下一帧,而卡顿的那一帧在一段时间执行完渲染后,会在最新的一帧到来时提交给显示器,展示最新变化

# 理解
页面渲染的越快,在 Hz 越大的屏幕上看着越丝滑,页面渲染的越慢则差异不大,只是 Hz 越大的越快恢复卡顿
每一帧的执行都是固定的,渲染超时在渲染完成后会在最新的一帧到来时提交给显示器显示,而这个渲染间隔的事件则继续展示卡顿之前的页面(卡顿现象)

渲染超时丢帧卡顿的三种情况

以 60HZ,每帧 16.67ms 为例

情况1:轻度超时(18ms)

js
// 预算16.6ms,实际用了18ms
// 结果:下一帧会被延迟约1.4ms
帧1: 18ms完成并显示但晚了1.4ms
帧2: 本来应该在16.6ms时开始实际在18ms时开始
帧2后续也会连锁延迟

视觉效果轻微抖动不明显

情况2:中度超时(30ms)

js
// 实际耗时30ms
帧1: 30ms完成
显示器: 16.6ms时已经发送第二次VSync但帧1还在渲染
第2个VSync信号被忽略
第3个VSync(33.2ms帧1刚完成

结果丢了一整帧屏幕画面16.6ms内没有更新

视觉效果明显卡顿能感知到跳跃

情况3:重度超时(100ms+)

js
// 实际耗时100ms
显示器连续发送了6次VSync信号(16.6ms × 6 ≈ 100ms
浏览器一直没响应

结果连续丢失6帧用户看到画面定格100ms

视觉效果明显冻结点鼠标都没反应