CPU 瓶颈
2023-03-06 20:59:41
当项目变得庞大、组件数量繁多时,就容易遇到 CPU 的瓶颈。比如我们渲染一万个 div 组件
主流浏览器刷新频率为 60Hz,即每(1000ms / 60Hz)16.6ms 浏览器刷新一次。
我们知道,JS 可以操作 DOM,GUI 渲染线程与 JS 线程是互斥的。所以 JS 脚本执行和浏览器布局、绘制不能同时执行。
也就是说在每 16.6ms 时间内,需要完成如下工作
- JS 脚本执行
- 样式布局
- 样式绘制
当 JS 执行时间过长,超出了 16.6ms,这次刷新就没有时间执行样式布局和样式绘制了。就会造成页面掉帧,造成卡顿。
如何解决这个问题呢?
答案是:在浏览器每一帧的时间中,预留一些时间给 JS 线程,React 利用这部分时间更新组件(可以看到,在 react 源码 中,预留的初始时间是 5ms)。
当预留的时间不够用时,React 将线程控制权交还给浏览器使其有时间渲染 UI,React 则等待下一帧时间到来继续被中断的工作。
这种将长任务分拆到每一帧中,像蚂蚁搬家一样一次执行一小段任务的操作,被称为时间切片(time slice)
开启 Concurrent Mode
tsx
// 通过使用ReactDOM.unstable_createRoot开启Concurrent Mode
// ReactDOM.render(<App/>, root);
ReactDOM.unstable_createRoot(root).render(<App />)
1
2
3
2
3
此时我们的长任务被拆分到每一帧不同的 task 中,JS 脚本执行时间大体在 5ms 左右,这样浏览器就有剩余时间执行样式布局和样式绘制,减少掉帧的可能性。·
所以,解决 CPU 瓶颈的关键是实现时间切片,而时间切片的关键是:将同步的更新变为可中断的异步更新。