- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章从框架作者角度聊:React调度算法的迭代过程由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
大家好,我卡颂.
React内部最难理解的地方就是「调度算法」,不仅抽象、复杂,还重构了一次.
可以说,只有React团队自己才能完全理解这套算法.
既然这样,那本文尝试从React团队成员的视角出发,来聊聊「调度算法」.
React在v16之前面对的主要性能问题是:当组件树很庞大时,更新状态可能造成页面卡顿,根本原因在于:更新流程是「同步、不可中断的」.
为了解决这个问题,React提出Fiber架构,意在「将更新流程变为异步、可中断的」.
最终实现的交互流程如下:
在render过程中,如果又触发交互流程,步骤2又选出一个更高优先级,则之前的render中断,以新的优先级重新开始render.
本文要聊的就是步骤2中的「调度算法」.
「调度算法」需要解决的最基本的问题是:如何从众多更新中选择其中一个更新的优先级作为本次render的优先级?
最早的算法叫做expirationTime算法.
具体来说,更新的优先级与「触发交互的当前时间」及「优先级对应的延迟时间」相关:
例如,高优先级更新u1、低优先级更新u2的updatePriority分别为0、200,则 。
代表u1优先级更高.
expirationTime算法的原理简单易懂:每次都选出所有更新中「优先级最高的」.
除此之外,还有个问题需要解决:如何表示「批次」?
「批次」是什么?考虑如下例子:
两种「修改状态的方式」都会创建更新,区别在于:
由于第二种方式的存在,更新之间可能有连续性.
所以「调度算法」计算出一个优先级后,组件render时实际参与计算「当前状态的值」的是:
「计算出的优先级对应更新」 + 「与该优先级相关的其他优先级对应更新」 。
这些相互关联,有连续性的更新被称为一个「批次」(batch).
expirationTime算法计算「批次」的方式也简单粗暴:优先级大于某个值(priorityOfBatch)的更新都会划为同一批次.
expirationTime算法保证了render异步可中断、且永远是最高优先级的更新先被处理.
这一时期该特性被称为Async Mode.
Async Mode可以解决以下问题:
这些问题统称为CPU密集型问题.
在前端,还有一类问题也会影响体验,那就是「请求数据造成的等待」。这类问题被称为IO密集型问题.
为了解决IO密集型问题的,React提出了Suspense。考虑如下代码:
其中:
假设请求三秒后返回,理想情况下,请求发起前后UI会依次显示为:
从用户的视角观察,有两个任务在并发执行:
Suspense带来了「多任务并发执行」的直观感受.
因此,Async Mode(异步模式)也更名为Concurrent Mode(并发模式).
那么Suspense对应更新的优先级是高还是低呢?
当请求成功后,合理的逻辑应该是「尽快展示成功后的UI」。所以Suspense对应更新应该是高优先级更新。那么,在示例中共有两类更新:
Suspense对应的高优IO更新,简称u0 。
每秒产生的低优CPU更新,简称u1、u2、u3等 。
在expirationTime算法下:
u0优先级最高,则u1及之后的更新都需要等待u0执行完毕后再进行.
而u0需要等待「请求完毕」才能执行。所以,请求发起前后UI会依次显示为:
从用户的视角观察,第二个div被卡住了3秒后突然变为4.
所以,只考虑CPU密集型场景的情况下,「高优更新先执行」的算法并无问题.
但考虑IO密集型场景的情况下,高优IO更新会阻塞低优CPU更新,这显然是不对的.
所以expirationTime算法并不能很好支持并发更新.
expirationTime算法在线Demo[1] 。
expirationTime算法最大的问题在于:expirationTime字段耦合了「优先级」与「批次」这两个概念,限制了模型的表达能力.
这导致高优IO更新不会与低优CPU更新划为同一「批次」。那么低优CPU更新就必须等待高优IO更新处理完后再处理.
如果不同更新能根据实际情况灵活划分「批次」,就不会产生这个bug.
重构迫在眉睫,并且重构的目标很明确:将「优先级」与「批次」拆分到两个字段中.
新的调度算法被称为Lane,他是如何定义「优先级」与「批次」呢?
对于优先级,一个lane就是一个32bit Interger,最高位为符号位,所以最多可以有31个位参与运算.
不同优先级对应不同lane,越低的位代表越高的优先级,比如:
「批次」则由lanes定义,一个lanes同样也是一个32bit Interger,代表「一到多个lane的集合」.
可以用位运算很轻松的将多个lane划入同一个批次:
上文提到的Suspense的bug是由于expirationTime算法不能灵活划定批次导致的.
lanes就完全没有这种顾虑,任何想划定为同一「批次」的优先级(lane)都能用位运算轻松搞定.
Lane算法在线Demo[2] 。
「调度算法」要解决两个问题:
expirationTime算法中使用的expirationTime字段耦合了这两个概念,导致不够灵活.
Lane算法的出现解决了以上问题.
[1]expirationTime算法在线Demo
https://codesandbox.io/s/usetransition-stop-reacting-passed-props-updates-forked-5e7lh 。
[2]Lane算法在线Demo
。
https://codesandbox.io/s/usetransition-stop-reacting-passed-props-updates-zoqm2?file=/src/index.js 。
原文链接:https://mp.weixin.qq.com/s/tkEYtRTrZovA4uVrfnNUDQ 。
最后此篇关于从框架作者角度聊:React调度算法的迭代过程的文章就讲到这里了,如果你想了解更多关于从框架作者角度聊:React调度算法的迭代过程的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我有一个带有一些功能的perl对象。每个功能从主程序中调用一次。我想并行运行某些功能以节省时间。由于某些功能取决于先前功能的结果,因此我无法将它们全部一起运行。 我想到了这样的事情: 对于每个函数,保
首先,我的代码在这里: import schedule # see https://github.com/dbader/schedule import crawler def job(): p
从 11 月 1 日开始,我必须使用quartz调度程序每4个月安排一次任务。我使用 cronExpression 来实现同样的目的。但 cronExpression 每年都会重置。所以我的任务将在
我有以下代码块,它调用两个请求,但略有延迟。 final ActorRef actor1 = getContext().actorOf( ActorClass.prop
考虑到 Linux 的情况,我们为每个用户堆栈都有一个内核堆栈,据我所知,每当发生上下文切换时,我们都会切换到当前进程的内核模式。 这里我们保存当前进程的当前状态,寄存器,程序数据等,然后调度器(不确
我有将东西移植到 OpenBSD 的奇怪爱好。我知道它有 pthreads 问题,但在 2013 年 5 月发布版本之前我不会升级。我使用的是 5.0,我对 pthreads 还很陌生。我已经学习了
给定一组任务: T1(20,100) T2(30,250) T3(100,400) (execution time, deadline=peroid) 现在我想将截止日期限制为 Di = f * Pi
使用 Django 开发一个小型日程安排 Web 应用程序,在该应用程序中,人们被分配特定的时间与他们的上级会面。员工存储为模型,与表示时间范围和他们有空的星期几的模型具有 OneToMany 关系。
我想了解贪婪算法调度问题的工作原理。 所以我一直在阅读和谷歌搜索一段时间,因为我无法理解贪心算法调度问题。 我们有 n 个作业要安排在单个资源上。作业 (i) 有一个请求的开始时间 s(i) 和结束时
这是流行的 El Goog 问题的变体。 考虑以下调度问题:有 n 个作业,i = 1..n。有 1 台 super 计算机和无限的 PC。每个作业都需要先经过 super 计算机的预处理,然后再在P
假设我有一个需要运行多次的蜘蛛 class My_spider(Scrapy.spider): #spider def 我想做这样的事 while True: runner = Cra
我已将 podAntiAffinity 添加到我的 DeploymentConfig 模板中。 但是,pod 被安排在我预计会被规则排除的节点上。 我如何查看 kubernetes 调度程序的日志以了
我已经使用 React - Redux - Typescript 堆栈有一段时间了,到目前为止我很喜欢它。但是,由于我对 Redux 很陌生,所以我一直在想这个特定的话题。 调度 Redux 操作(和
我想按照预定的计划(例如,周一至周五,美国东部时间晚上 9 点至 5 点)运行单个 Azure 实例以减少账单,并且想知道最好的方法是什么。 问题的两个部分: 能否使用服务管理 API [1] 按预定
假设最小模块安装(为了简单起见),Drupal 的 index.php 中两个顶级功能的核心“职责”是什么? ? drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); me
我正在尝试使用 Racket(以前称为 PLT Scheme)连接 URL 调度。我查看了教程和服务器文档。我不知道如何将请求路由到相同的 servlet。 具体例子: #lang 方案 (需要网络服
我想在 Airflow (v1.9.0) 上运行计划。 我的DAG需要在每个月底运行,但我不知道如何编写设置。 my_dag = DAG(dag_id=DAG_ID, cat
我正在尝试在“httpTrigger”类型函数的 function.json 中设置计划字段,但计时器功能似乎未运行。我的目标是拥有一个甚至可以在需要时进行调度和手动启动的功能,而不必仅为了调度而添加
我正在尝试制定每周、每月的 Airflow 计划,但不起作用。有人可以报告可能发生的情况吗?如果我每周、每月进行安排,它就会保持静止,就好像它被关闭一样。没有错误信息,只是不执行。我发送了一个代码示例
我希望每两周自动更新一次我的表格。我希望我的函数能够被 firebase 调用。 这可能吗? 我正在使用 Angular 2 Typescript 和 Firebase。 最佳答案 仅通过fireba
我是一名优秀的程序员,十分优秀!