Little-Gee / blog

15 stars 11 forks source link

2.瓶颈与方案 #19

Open Little-Gee opened 1 year ago

Little-Gee commented 1 year ago

React 在老的架构中是没有 fiber 的,执行渲染函数生成 vdom 后,直接转成了 真实DOM,新架构中先将 vdom 转成 fiber,再渲染成真实节点。

为什么要多此一举呢?

这就要从遇到的瓶颈说起了。

一、瓶颈

瓶颈主要分为两类:由 CPU 造成的和由 IO 造成的。

1.CPU 瓶颈

主流浏览器的刷新频率(FPS)一般是 60Hz,也就是屏幕每秒刷新 60 次,那么 1000 / 60 = 16.6,每帧大概是 16.6ms。 在这一帧中,浏览器既需要完成 JS 脚本的执行,也需要完成布局、绘制工作。

image

由于 JS 线程和 GUI 渲染线程是互斥的,无法同时执行,那么如果 JS 执行时间过长(比如写个执行时间很长的 while 循环),那么就没时间执行后面的布局和绘制了,页面就会卡顿。

2.IO 瓶颈

IO 瓶颈指的是网络延迟,需要等待数据返回后才能进行进一步操作。

二、方案

1.CPU 瓶颈

针对 CPU 瓶颈,如果让执行时间过长的任务拆分成一个个小任务,放到每一帧中去执行不就好了?这就是时间切片

2.IO 瓶颈

网络延迟实际上是无法控制的,但是换种思路,如果让用户觉得延迟小甚至不觉得有延迟不就好了? React 的做法是将人机交互研究的结果整合到真实的 UI 中,通过控制组件渲染的优先级来解决问题。

举两个例子:

为了实现上述的效果,关键是将同步的更新变为异步可中断更新

image (1)

三、架构的变化

为了实现异步可中断更新,React 的架构进行了升级。

1.老架构

在 React15 中,架构可以分为两层:

在老的架构中,Reconciler 是递归更新的。 每次有更新发生时,组件会重新调用render,生成新的虚拟DOM新旧虚拟DOM通过diff算法进行对比,找出变化。 但是通过递归处理的问题在于不可中断,如果虚拟DOM层级很深,递归时间过长,那页面卡顿就无法避免了。

2.新架构

在 React16 中,架构新增了调度器这一层:

除了加入SchedulerReconciler也发生了重大变化,引入了Fiber虚拟DOM不再直接渲染成真实的节点,而是先转为Fiber节点,这个转换过程是可以中断的。然后配合优先级调度,在空余时间完成转换,全部转换完成后再交给Renderer进行渲染(渲染是不可中断的)。

由此,React 实现了异步可中断更新。