React18原理: Fiber架构下的单线程CPU调度策略

概述

  • React 的 Fiber 架构, 它的整个设计思想就是去参考CPU的调度策略
  • CPU现在都是多核多进程的,重点研究的是
    • CPU是单核单线程,它是如何调度的?
    • 为什么要去研究单线程的CPU?
  • 浏览器中的JS它是单线程的
  • JS 的执行线程和浏览器的渲染GUI 是互斥的
  • 渲染和JS的执行都用同一个线程,因为一次只能做一件事情,所以互斥
  • 所以,React整个架构的整个调度都是去参考 CPU 的

单线程CPU调度策略


单处理器进程调度策略

  • 1 ) 先到先得(First-Come-First-Served,FCFS)

    • 可以把 CPU 理解为一个办事窗口, 比如说排队,有的人办的慢,有的人办的快
    • 比如,有人办事只需要一分钟,有的人却很墨迹,办事要半个小时
    • 办事墨迹的人,后面的人都一直在等着,所以这个先到先得的策略
    • 对于CPU来讲,其实就是不合理的,不能谁先来就先执行
    • 因为有的人比较着急(优先级高),放在后面不适合
    • 这是最简单的调度策略,简单说就是没有调度,谁先来谁就先执行
    • 执行完毕后就执行下一个,不过如果中间某些进程因为I/O阻塞了
    • 这些进程可能会重新排队了,需要留意的事:
    • FCFS对短进程不利
      • 短进程即执行时间非常短的进程
      • 可以用饭堂排队来比喻:
        • 在饭堂排队打饭的时候,一个人打包好几份
        • 这些人就像长进程一样,霸占着CPU资源
        • 后面排队只打一份的人会觉得很吃亏
        • 打一份的人会觉得它们优先级应该更高,毕竟它们花的时间很短
        • 反正你打包那么多份再等一会也是可以的,何必让后面那么多人等这么久…
    • FCFS对I/0密集不利
      • I/O密集型进程(这里特指同步I/O)在进行I/O操作时
      • 会阻塞休眠,这会导致进程重新被放入就绪队列,等待下一次
      • 可以类比银行部门办业务:假设CPU一个窗口、I/O一个窗口
      • 在CPU窗口好不容易排到你了,这时候发现一个不符合条件或者漏办了
      • 需要去 I/O 搞一下,要去I/O窗口排队,I/O执行完了
      • 到CPU窗口又得重新排队,这样,似乎也是不合理的
    • 所以FCFS这种原始的策略在单处理器进程调度中并不受欢迎

  • 2 )轮转调度

    • 轮转调度它是基于时钟的一种抢占策略
    • CPU的时钟其实就是根据它的这个帧幅周期
    • 这个就跟吃大锅饭一样,也没有体现一种权重
    • 最后, 比如说有人有急事,那这个时候搞轮转,也是不合适的
    • 它属于抢占策略中最简单的一种:
      • 公平地给每一个进程一定的执行时间,当时间消耗完毕或阻塞
      • 操作系统就会调度其他进程,将执行权抢占过来
    • 决策模式:
      • 抢占策略相对应的有非抢占策略
      • 非抢占策略指的是让进程运行直到结束、阻塞(如I/O或睡眠)
      • 或者主动让出控制权,抢占策略支持中断正在运行的进程
      • 将主动权掌握在操作系统这里,不过通常开销会比较大
    • 这种调度策略的要点是
      • 确定合适的时间片长度:太长了,长进程霸占太久资源
      • 其他进程会得不到响应(等待执行时间过长)
      • 这时候就跟上述的FCFS没什么区别了
      • 太短了也不好,因为进程抢占和切换都是需要成本的
      • 而且成本不低,时间片太短,时间可能都浪费在上下文切换上了
      • 导致进程干不了什么实事
    • 因此时间片的长度最好符合大部分进程完成一次典型交互所需的时间
    • 轮转策略非常容易理解,只不过确定时间片长度需要伤点脑筋
    • 另外和FCFS一样,轮转策略对I/O进程还是不公平

  • 3 )最短进程优先(Shortest Process Next,SPN)

    • 什么是短进程呢?
    • 短进程就跟排队一样,比如,我办事一分钟,我就是短进程
    • 你墨迹半个小时,你就是长进程
    • 所以,可以设计一种调度策略叫短进程优先
    • 如果说,我办的快,我就优先,那慢的一直在后面等着
    • 这样好像也有点不对劲,所以这个也有缺陷
    • 长进程就会饥饿,可能永远得不到响应,没法去执行, 所以,这个也不行
    • 上面说了先到先得策略对短进程不公平
    • 最短进程优先索性就让最短的进程优先执行
    • 也就是说:按照进程的预估执行时间对进程进行优先级排序
    • 先执行完短进程,后执行长进程,这是一种非抢占策略
    • 这样可以让短进程能得到较快的响应
    • 但怎么获取或者评估进程执行时间呢?
      • 一是让程序的提供者提供,这不太靠谱
      • 二是由操作系统来收集进程运行数据,并对它们进程统计分析
    • 例如最简单的是计算它们的平均运行时间
    • 不管怎么说都比上面两种策略要复杂一点
    • SPN的缺陷是:
      • 如果系统有大量的短进程,那么长进程可能会饥饿得不到响应
      • 另外因为它不是抢占性策略,尽管现在短进程可以得到更多的执行机会
      • 但是还是没有解决FCFS的问题:一旦长进程得到CPU资源
      • 得等它执行完,导致后面的进程得不到响应
  • 其他策略

    • 最短余(Shortest Remaining Time,SRT)
    • 最高响应比优先(HRRN)
    • 反馈法
    • 这里不再举例

前端框架解决上述问题的方向

  • 对于前端框架来说,解决这种问题有三个方向:
    • 1 )优化每个任务,让它有多快就多快。挤压CPU运算量
      • Vue 选择的是这一种,对于Vue来说,使用模板让它有了很多优化的空间
      • Vue使用依赖收集,基于Proxy来监听数据的变化,在get时收集依赖,在set时
      • 触发依赖渲染页面,配合响应式机制可以让Vue精确地进行节点更新
    • 2 )快速响应用户,让用户觉得够快,不能阻塞用户的交互(React分片)
      • React选择了这一种,一个任务,假如说要运行1秒钟
      • 那React通过分片之后,可能用了1.2秒,但是它却让你感觉很快
      • 实际上它的执行时间是没有降低的,但是它会让你感觉快
      • React 的 Reconcilatin 是 CPU 密集型的操作,它就相当于我们上面讲的
      • 长进程,所以初衷和进程调度一样,要让高优先级的进程或短进程优先运行
      • 不能让长进程长期霸占资源
    • 3 )尝试Worker多线程
      • 要保证状态和视图的一致性相当麻烦,这里不再赘述

React 不同模式的效果对比

1 )同步模式下的 React, 可以看到,阻塞比较严重

2 ) 异步 Concurrent 模式下的 React, 可以看到,非常流畅

React是怎么优化的

  • 为了给用户制造一种应用很快的假象,不能让一个程序长期霸占着资源
  • 可以将浏览器的渲染、布局、绘制、资源加载(例如HTML解析)、事件响应、脚本执行视作操作系统的进程
  • 需要通过某些调度策略合理地分配CPU资源,从而提高浏览器的用户响应速率,同时兼顾任务执行效率
  • 所以React通过Fiber架构,让 Reconcilation 过程变成可被中断
  • 适时地让出CPU执行权,让浏览器及时地响应用户的交互
<think>好的,我现在需要处理用户关于Web面试经验总结的请求。首先,用户可能希望得到全面的面试准备指导,涵盖前端、后端以及常见问题的解答。我要确保回答结构清晰,分点列出,符合用户提到的系统级指令中的中文回答和正确使用LaTeX格式的要求。 首先,用户可能想知道前端面试的重点。HTML/CSS、JavaScript框架和项目经验是关键点。需要注意每个部分的具体细节,比如HTML5新特性、盒模型、Flex布局等。在JavaScript部分,闭包、原型链、ES6特性都是常见问题,需要提及。框架方面,React和Vue的区别以及生命周期是常问的,可能需要用行内公式示例,比如虚拟DOM的diff算法时间复杂度$O(n)$。 然后是后端面试,包括语言基础、数据库、系统设计和项目经验。比如Java的集合框架、多线程,数据库的索引优化、事务隔离级别。系统设计部分,RESTful API设计原则和分布式系统问题如缓存穿透需要解释。这里可能需要用独立公式,比如CAP定理的公式,但用户示例中没有使用,所以暂时不考虑,除非必要。 接下来是常见问题,如项目难点、技术学习、团队协作。这些需要给出回答思路,帮助用户准备具体例子。此外,算法题也是重点,需要提到LeetCode和《剑指Offer》,可能涉及时间复杂度的计算,比如快速排序的平均复杂度$O(n \log n)$。 然后生成相关问题,确保覆盖用户可能感兴趣的扩展方向,如前端性能优化、后端高并发设计、项目亮点描述等。最后检查引用部分,用户示例中有引用标识,但当前内容中没有引用来源,可能需要添加,但用户提供的参考信息中没有具体引用来源,所以可能忽略或假设引用来自常见资料。 还要注意LaTeX的正确使用,所有行内数学表达式用$...$,独立公式用$$...$$,但用户示例中大部分是行内的,如时间复杂度。确保代码块用正确的语法,比如Python示例,但这里可能涉及JavaScript或其它语言的代码,但用户问题不涉及具体代码,所以可能不需要。 最后整理结构,确保各部分清晰,语言简洁,符合中文表达习惯,避免使用Markdown格式,使用自然的分段和标号。检查是否遗漏重要点,比如面试软技能、行为问题等,但用户可能更关注技术方面,所以集中在技术准备上。</think># Web面试经验总结 ## 一、前端面试重点 ### 1. HTML/CSS核心 - HTML5新特性:语义化标签(如`<article>`)、Web Storage、WebSocket - CSS盒模型:标准盒模型与怪异盒模型对比,通过`box-sizing`属性切换 - 布局方案:Flex布局实现响应式设计,Grid布局二维排版,浮动清除技巧 - 性能优化:雪碧图实现原理(通过$background-position$定位),重绘与回流优化 ### 2. JavaScript进阶 - 闭包应用场景:模块化开发中实现私有变量,柯里化函数实现 - 原型链机制:`__proto__`与`prototype`关系图解,`new`操作符实现原理 - ES6特性:箭头函数`this`绑定规则,Promise异步处理链,`let/const`暂时性死区 - 框架原理:虚拟DOM的diff算法时间复杂度$O(n)$,Vue双向绑定实现(Object.defineProperty) ## 二、后端面试要点 ### 1. 语言基础 - Java集合框架:HashMap扩容机制(负载因子0.75,容量翻倍) - 并发编程:线程池参数设置(核心线程数=CPU核数+1),synchronized锁升级过程 - 设计模式:Spring框架中的单例模式实现(注册式单例),代理模式在AOP中的应用 ### 2. 数据库优化 - 索引设计:B+树高度计算(假设每页16KB,单记录200B,3层可存$10^6$级数据) - 事务隔离:MVCC实现原理(版本链与ReadView机制),解决幻读的Next-Key Lock - 慢查询优化:通过`EXPLAIN`分析执行计划,关注`type`列(最优const到最差ALL) ## 三、高频面试问题 1. **项目难点突破** "在电商促销系统开发中,通过二级缓存(Redis+本地缓存)解决库存超卖问题,采用Lua脚本保证原子性[^1]" 2. **技术学习路径** "系统学习React源码时,先理解Fiber架构的链表结构,再分析调度器的工作循环" 3. **团队协作案例** "在前后端联调中,使用Swagger定义接口规范,通过Mock.js生成测试数据提升协作效率" ## 四、算法准备建议 - LeetCode刷题策略:按类型分类(数组->链表->树),每日保持3题练习量 - 重点题型:字符串处理(KMP算法时间复杂度$O(n+m)$)、动态规划(背包问题状态转移方程) - 白板编程:先阐述思路(如快速排序分治策略),再编写可运行代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值