React18源码: task任务调度和时间分片

Hermes-Agent:Rust原生AI任务调度中间件解析 AI代理(Agent)是实现自动化工作流的核心范式,其本质是将自然语言指令编译为可执行的动作序列。Hermes-Agent 并非大模型推理引擎或通用框架,而是一个面向本地化、可审计与低延迟场景的 Rust 原生任务调度中间件,专注解决模型能力碎片化与执行链路不可控问题。它通过声明式 YAML 定义动作依赖、利用 Rust 零成本抽象保障系统级性能,并深度集成 SQLite、curl、systemd 等原生能力。典型应用场景包括本地会议记录分析、飞书/钉钉多源数据协同处理、日志异常自动告警等需要高确定性与低延 阅读详情

任务队列管理

  • 调度的目的是为了消费任务,接下来就具体分析任务队列是如何管理与实现的

  • 在 Scheduler.js 中,维护了一个 taskQueue,

  • 任务队列管理就是围绕这个 taskQueue 展开

    // Tasks are stored on a min heap
    var taskQueue - [];
    var timerQueue = [];
    
  • 注意

    • taskQueue一个堆数
    • 源码中除了 taskQueue 队列之外还有一个 timerQueue 队列, 这个队列是预留给延时任务使用的

创建任务

  • 在 unstable_scheduleCallback 函数中

    // 省略部分无关代码
    function unstable_scheduleCallback(prioritylevel, callback, options) {
      // 1. 获取当前时间
      var currentTime = getCurrentTime();
      var startTime;
      if (typeof options === 'object' && options !== null) {
        //从函数调用关系来看,,所有调用 unstable_scheduleCallback 都未传入options
        // 所以省略延时任务相关的代码
      } else {
        startTime = currentTime;
      }
      //  2. 根据传入的优先级,设置任务的过期时间 expirationTime
      var timeout;
      switch (priorityLevel) {
        case ImmediatePriority:
          timeout = IMMEDIATE_PRIORITY_TIMEOUT;
          break;
        case UserBlockingPriority:
          timeout = USER_BLOCKING_PRIORITY_TIMEOUT;
          break;
        case IdlePriority:
          timeout = IDLE_PRIORITY_TIMEOUT;
          break;
        case LowPriority:
          timeout = LOW_PRIORITY_TIMEOUT;
          break;
        case NormalPriority:
        default:
            timeout = NORMAL_PRIORITY_TIMEOUT;
            break
      }
    
      var expirationTime = startTime + timeout;
      // 3.创建新任务
      var newTask = {
        id: taskIdCounter ++,
        callback,
        priorityLevel,
        startTime,
        expirationTime,
        sortIndex: -1,
      }
      if (startTime > currentTime) {
      } else {
        newTask.sortIndex = expirationTime;
        // 4. 加入任务队列
        push(taskQueue, newTask);
        // 5.请求调度
        if (!isHostCallbackScheduled && !isPerformingWork) {
          isHostCallbackScheduled = true;
          requestHostCallback(flushWork);
        }
      }
      return newTask;
    }
    

消费任务

  • 创建任务之后,最后请求调度 requestHostCallback(flushwork)(创建任务源码中的第5步)

  • flushWork 函数作为参数被传入调度中心内核等待回调

  • requestHostCallback 函数是调度内核中的一个

  • 在调度中心中只需下一个事件循环就会执行回调,最终执行 flushwork

    // 省略无关代码
    function flushWork(hasTimeRemaining, initialTime) {
      //1.做好全局标记,表示现在已经进入调度阶段
      isHostCallbackScheduled = false;
      isPerformingWork - true;
      const previousPrioritylevel = currentPriorityLevel;
      try {
        // 2.循环消费队列
        return workLoop(hasTimeRemaining, initialTime);
      } finally {
        // 3.还原全局标记
        currentTask = null;
        currentPriorityLevel = previousPriorityLevel;
        isPerformingWork = false;
      }
    }
    
  • flushwork中调用了 workLoop 队列消费的主要逻辑是在workLoop函数中

  • 这就是前面提到的任务调度循环

    //省略部分无关代码
    function workLoop(hasTimeRemaining, initialTime) {
      let currentTime = initialTime; //保存当前时间,用于判断任务是否过期
      currentTask = peek(taskQueue); //获取队列中的第一个任务
      while (currentTask !== null) {
        if(
          currentTask.expirationTime > currentTime &&
          (!hasTimeRemaining || shouldYieldToHost())
        ) {
          // 虽然currentTask没有过期,但是执行时间超过了限制(毕竟只有5ms, shouldYieldToHost()返回true)
          break;
        }
        const callback = currentTask.callback;
        if (typeof callback === 'function') {
          currentTask. callback = null;
          currentPrioritylevel = currentTask.prioritylevel;
          const didUserCallbackTimeout = currentTask.expirationTime <= currentTime;
          // 执行回调
          const continuationCallback = callback(didUserCallbackTimeout);
          currentTime = getCurrentTime();
          // 回调完成,判断是否还有连续(派生)回调
          if (typeof continuationCallback === 'function') {
            // 产生了连续回调(如fiber树太大,出现了中断渲染),保留currentTask
            currentTask.callback = continuationCallback;
          } else {
            // 把currentTask移出队列
            if (currentTask === peek(taskQueue)) {
              pop(taskQueue);
            }
          }
        } else {
          // 如果任务被取消(这时currentTosk.callback ~ null),将其移出队列
          pop(taskQueue);
        }
        // 更currentTask
        currentTask = peek(taskQueue);
      }
      if (currentTask !== null) {
        return true; // 如果 task 队列没有清空,返回 true。寻待调度中心下一次回调
      } else {
        return false; // task 队列已经清空,返回false.
      }
    }
    
  • workLoop 就是一个大循环,虽然代码也不多,但是非常精髓

  • 在此处实现了时间切片(time slicing)和fiber树的可中断渲染

  • 这2大特性的实现,都集中于这个while循环

  • 每一次while循环的退出就是一个时间切片,深入分析while循环的退出条件:

    • 1.队列被完全清空:这种情况就是很正常的情况,一气呵成,没有遇到任何阻碍.
    • 2.执行超时:在消费taskQueue时,在执行 task.callback之前,都会检测是否超时,所以超时检测是以task为单位
      • 如果某个 task.callback 执行时间太长(如:fiber树很大,或逻辑很重)也会造成超时
      • 所以在执行task.cal1back过程中,也需要一种机制检测是否超时,如果超时了就立刻暂停task.callback的执行.

时间切片原理

  • 消费任务队列的过程中,可以消费1~n个task,甚至清空整个queue.
  • 但是在每一次具体执行task.callback之前都要进行超时检测,如果超时可以立即退出循环并等待下一次调用.

可中断渲染原理

  • 在时间切片的基础之上,如果单个task.callback执行时间就很长(假设200ms)
  • 就需要task.callback自己能够检测是否超时,所以在fiber树构造过程中
  • 每构造完成一个单元,都会检测一次超时,如遇超时就退出fiber树构造循环,并返回一个新的回调函数
  • 就是 continuationCallback 并等待下一次回调继续未完成的fiber树构造

节流防抖{#throttle-debounce}

  • 通过以上分析,已经覆盖了 scheduler 包中的核心原理

  • 现在再次回到 react-reconciler包中,在调度过程中的关键路径中,还需要理解一些细节

  • 在 Renconciler 运行流程中总结的4个阶段中,注册调度任务属于第2个阶段

  • 核心逻辑位于ensureRootIsScheduled函数中

    // 省略部分无关代码
    function ensureRootIsscheduled(root: FiberRoot, currentTime: number) {
      // 前半部分:判断是否需要注册新的调度
      const existingcallbackNode = root.callbackNode;
      const nextLanes = getNextLanes(
        root,
        root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes,
      );
      const newCallbackPriority = returnNextLanesPriority();
      if (nextLanes === NoLanes) {
        return;
      }
      // 节流防抖
      if (existingcallbackNode !== null) {
        const existingcallbackpriority = root.callbackpriority;
        if (existingCallbackPriority === newCallbackPriority){
          return;
        }
        cancelCallback(existingcallbackNode);
      }
    
      // 后半部分:注册调度任务省略代码
      // 更新标记
      root.callbackPriority = newcallbackPriority;
      root.callbackNode = newcallbackNode;
    }
    
  • 正常情况下,ensureRootIsScheduled 函数会与scheduler包通信,最后注册一个task并等待回调.

  • 1.在task注册完成之后,会设置fiberRoot对象上的属性,代表现在已经处于调度进行中

  • 2.再次进入ensureRootIsScheduled时

    • 比如连续2次 setState,第2次 setState同样会触发
    • reconciler运作流程中的调度阶段,如果发现处于调度中
    • 则需要一些节流和防抖措施,进而保证调度性能.
    • a.节流
      • 判断条件:existingCallbackPriority == newCallbackPriority
      • 新旧更新的优先级相同,如连续多次执行setState
      • 则无需注册新task(继续沿用上一个优先级相同的task),直接退出调用
    • b.防抖
      • 判断条件: existingCallbackPriority !== newCallbackPriority
      • 新旧更新的优先级不同,则取消旧task, 重新注册新task
  • 总结

    • 主要分析了scheduler包中调度原理
    • 也就是React两大工作循环中的任务调度循环
    • 时间切片和可中断渲染等特性在任务调度循环中的实现
    • scheduler包是React运行时的心脏,为了提升调度性能
    • 注册task之前,在react-reconciler包中做了节流和防抖等措施
【React原理 - 任务调度和时间分片详解】 本文从源码角度分析从状态更新到合成事件到优先级转换,一步一步到Scheduler任务调度。详细介绍了其中内部实现原理和逻辑。 阅读详情

相关推荐

React源码解读之任务调度

React设计体系如人类社会一般,拨动时间轮盘的那一刻,你便成了穿梭在轮片中的一粒细沙,角逐过程处处都需要亮出你的属性,你重要吗?你无可替代吗?你有特殊权限吗?没有,那不好意思,请继续在轮片中循环。属于你的生命之火殆尽,前来悼念之人很多,这幕,像极了出生时的场景。干啥玩意儿,这是技术文章不是抒情散文!下面进入正题。创建的准备上一节已经说明了,主要定义与更新相关的数据结构和变量,计算过期时间等。

weixin_59558923的博客 731

React 探秘(三): 时间切片

react使用时间切片提升渲染性能,在熟知原理后,同样我们在业务中也有很多优化场景可以使用到。例如:高频埋点批量切片上传,大量 dom 节点操作等等。

qq_44983621的博客 1926

React中的高优先级任务插队机制

在React的concurrent模式下,低优先级任务执行过程中,一旦有更高优先级的任务进来,那么这个低优先级的任务会被取消,优先执行高优先级任务。等高优先级任务做完了,低优先级任务会被重新做一遍。 我们用一个具体的例子来理解一下高优先级任务插队。 有这样一个组件,state为0,进入页面,会调用setState将state加1,这个作为低优先级任务。React开始进行更新,在这个低优先级任务尚未完成时,模拟按钮点击,state加2,这个作为高优先级任务。可以看到,页面上的数字变化为0 -> 2

与其临渊羡鱼,不如退而结网 1425

React 第三十六章 Scheduler 任务调度

用于在 React 应用中进行任务调度。它可以帮助开发人员在处理复杂的任务和操作时更好地管理和优化性能。关于 Scheduler 在React 如何渲染的可以参考下面我们根据流程图先简单的了解 Scheduler 的调度过程Scheduler 维护两个队列,分别存放普通任务和延时任务当接收的是普通任务时,会加入普通任务队列,然后执行。根据环境创建宏任务(主要创建的就是),然后执行。该方法实际上主要就是在调用。

aXin_li的博客 1592

React中的时间切片:优化JavaScript的执行

它将长时间任务切分为较小的任务片段,并在主线程空闲时执行这些任务片段,从而提高应用程序的响应性能。它通过将长时间运行的任务分解为较小的可中断的片段,从而避免阻塞主线程,提高应用程序的响应性能。它通过将长时间运行的任务分解为较小的可中断的片段,从而避免阻塞主线程,提高应用程序的响应性能。在本文中,我们将探讨React中时间切片的实现方式,并提供相应的源代码示例。它将长时间任务切分为较小的任务片段,并在主线程空闲时执行这些任务片段,从而提高应用程序的响应性能。的函数式组件,它具有一个计数器和一个增加按钮。

python_bug262的博客 322

Android汽车服务篇(一) CarService

本文主要说明了CarService这一系统服务的启动流程,以及一些关键成员的创建和初始化流程.同时简单介绍了一下客户端是如何获取和使用CarService对象, 如上文介绍的, CarService对象只是获取各个Manager的媒介,它本身并不承担管理传感器.空调等具体的任务.如果要获取车辆的相关信息,如车速, 车内空调温度,诊断信息, 或对车辆进行相关的控制,如升高和降低空调温度,控制座椅和车窗, 调节音量等,就要通过具体的Manager中的API和对应的服务来实现了.

u012514113的专栏 8148

React 任务调度

React 任务调度源码探究

1352

手把手教你用scRNA-seq和scTCR-seq分析CD8⁺ T细胞在免疫治疗中的动态变化

本文详细介绍了如何整合单细胞RNA测序(scRNA-seq)与单细胞TCR测序(scTCR-seq)技术,深入解析CD8⁺ T细胞在癌症免疫治疗中的动态变化。通过从数据预处理、细胞亚群鉴定到TCR克隆追踪的完整分析流程,揭示了T细胞的功能状态转变与克隆演化规律,为理解免疫应答机制和开发精准治疗策略提供了关键方法学指导。

p8q9r0的博客 570

其实,很多前端开发岗都是混进去再说…

面试前端开发,主要就是面试先混进去再说,整理了一下面试中需要注意的问题:1. JavaScript 底层理解不足问题表现:- 对闭包、事件循环、原型链等概念只能背定义,无法结合业务场景解释(如闭包在模块化中的应用)。- 手写代码时逻辑混乱。建议:-深入 V8 机制:搞懂微任务/宏任务调度、内存泄漏排查-手写关键代码:至少能独立实现 `bind`、`new`、`防抖节流`,并解释优化思路。2. 框架只会用,不懂原理问题表现:- 能写 React/Vue 组件,但说不清;

2401_86373285的博客 1574

19-5 ACC 自适应巡航控制系统需求

本专题由深圳季连AIgraphX李博及团队出品,主要讲解ACC自适应巡航控制系统的开发与仿真测试。具体说来,包括ACC标准/法规分析、系统需求、系统架构、软件需求、软件架构、算法建模、验证场景分析、仿真实验搭建等内容。 本节主要讲ACC系统需求。

AIgraphX 1090

C# 量子级跨平台开发:用Uno Platform实现Windows、iOS、Android的“量子纠缠”UI同步

墨瑾轩推出编程学习平台,通过XAML的“量子纠缠”技术,实现跨平台开发的高效与一致性。传统方案中,多平台代码重复率高,UI差异大,而量子级方案则通过一套代码构建全平台应用,UI原子化同步,开发效率提升5倍。Uno Platform的“量子纠缠”架构解决了代码碎片化、性能瓶颈和调试难题,实现UI原子化同步、性能提升300%和跨平台数据无缝同步。核心架构包括XAML的跨平台渲染、MVVM的量子叠加态架构、平台差异的量子退相干处理以及性能优化的量子隧穿效应,为开发者提供高效、一致的跨平台开发体验。

java专栏 1165

【推荐一款比腾讯WorkBuddy、阿里悟空更好用能力更强的办公自进化 Agent 】开源 DeepThink AI Agent

DeepThink, 企业级自主 Agent 超级智能体自进化平台,从 Harness Engineering 到 Loop Engineering 范式的先行者,是面向企业客户的新一代 AI 基础设施(AI Infra)。DeepThink 平台以多 Agent 协作框架为核心,融合 AI 自主编程(AI Coding)、自主进化(Self-Evolving)、全栈可观测性(Full-Stack Observability)、Bug 自修复闭环(Bug Auto-Fix Loop)Coding Agent

AI天才研究院 1155

Docker Desktop 从 C 盘迁移到 D 盘的正确方法

本文介绍了三种将Docker数据目录从C盘迁移到D盘的方案。方案1针对WSL2用户,通过导出/导入虚拟磁盘实现迁移;方案2采用软链接方式,适合所有Docker模式;方案3则建议重装Docker到D盘。其中WSL2迁移方案(方案1)最为稳定可靠,推荐使用。文章详细说明了各方案的操作步骤及注意事项,并提供了迁移后常见问题的解决方法,帮助用户彻底解决Docker占用C盘空间的问题。

sg_knight的专栏 2178

2026面试预判及实际面试

本文摘要总结了多个前端开发岗位的面试问题和答案,涵盖Vue3、ECharts、数据可视化、JavaScript核心概念等内容。 Vue3高频问题 组合式API相比选项式API的优势在于逻辑内聚、更好的TS支持和复用性。 状态管理推荐Pinia,轻量且支持组合式API风格。 动态路由和权限控制通过router.addRoute和路由守卫实现。 响应式原理基于Proxy和Reflect,解决了Vue2的局限性。 ECharts与数据可视化 性能优化包括数据聚合、懒渲染和dataZoom区域缩放。

Mr.小灰狼_随笔 581

Ubuntu\linux,加载mcp2515的驱动,链接mcp2515,mcp2515的这个驱动默认在linux内核中。jetson nao、香橙派、树莓派

3. 其他文章,还要进行驱动编译就比较复杂了(不推荐)1.树莓派+MCP2515+

pvmsmfchcs的博客 1569

面向元数据的 SAP UI 中枢:namespace sap.ui.mdc 全景解析

如果把应用前端比作一条数据到交互的装配线,sap.ui.mdc 就是那条线的标准化工装:以 PropertyInfo 描述原料,以 Delegate 定义装配方法,以 p13n 与 VariantManagement 交付面向个体的最终产物;而 Condition Model、Operator 与 ValueHelp 则让输入与筛选的语义落地。与 OData V4 服务与 Fiori Elements 宏构件组合使用时,它能在保持一致体验的同时,给自由式开发者留下足够的可编排空间。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 240

react源码解析——react 任务调度:scheduleWork

react 任务调度

weixin_47338877的博客 640

深度学习实战12(进阶版)-利用Dewarp实现文本扭曲矫正

大家好,我是微学A1, 我们在生活中会看到一些拍摄扭曲的图片,我们在通过OCR识别的时候,因为扭曲的厉害,而无法识别,我们需要对图片进行处理。

微学AI的博客 3157

react scheduler之任务调度和时间切片学习笔记

我们日常使用App,浏览网页时,有两类场景会制约快速响应:CPU的瓶颈: 当遇到大计算量的操作或者设备性能不足使页面掉帧,导致卡顿IO的瓶颈: 发送网络请求后,由于需要等待数据返回才能进一步操作导致不能快速响应。

奔跑的小猪仔 1413

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

React18原理: React核心对象之Update、UpdateQueue、Hook、Task对象

updateQueue是fiber对象的一个属性,它们之间数据结构和引用关系如下。注意task中没有next属性,它不是一个链表,其顺序是通过堆排序来实现的。小顶堆数组,始终保证数组中的第一个task对象优先级最高。2 )Update对象相关的数据结构。Hook与fiber的关系。

Wang的专栏 1818

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

【React源码】(七)React 调度原理(scheduler)

本节主要分析了scheduler包中调度原理, 也就是React两大工作循环中的任务调度循环. 并介绍了时间切片和可中断渲染等特性在任务调度循环中的实现.scheduler包是React运行时的心脏, 为了提升调度性能, 注册task之前, 在包中做了节流和防抖等措施.

weixin_44828588的博客 1741

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

《深入理解react》之调度引擎——Scheduler

实际上 Scheduler 中一共维护了两个队列,本文并没有提到关于timerQueue的相关信息,那是因为在 react 的调度流程中基本不会涉及到timerQueue所以如果单纯理解 react 其实以上的知识已经足够,出于篇幅原因,timerQueue 相关的信息我会在后续的文章中进行详细分析。如果你喜欢这样的行文风格,可以关注我的《深入理解react》专栏,持续更新中…当前时间startTime。

weixin_50786692的博客 1997

六、深入理解React中普通任务的调度

React中普通任务的调度

weixin_43854624的博客 507

React Fiber 架构深度解析:时间切片与性能优化的核心引擎

在 React 生态中,性能优化始终是开发者关注的焦点。React 16 引入的 Fiber 架构,通过时间切片(Time Slicing)技术,彻底改变了 React 的渲染机制,为复杂应用的流畅运行提供了有力保障。本文将深入探讨 React Fiber 架构的核心概念,特别是时间切片技术,并通过手写 Fiber 节点结构来加深理解。

专研技术的大学生:会点Java和前端 1592

【React】React学习:从初级到高级(三)

随着应用不断变大,应该更有意识的去关注应用状态如何组织,以及数据如何在组件之间流动。冗余或重复的状态往往是缺陷的根源。

分享自己学习过程获得的一些知识 814
上一篇: React18源码: schedule任务调度messageChannel
下一篇: React18源码: Fiber树中的全局状态与双缓冲
Wang's Blog
博客等级 码龄12年 7434粉丝 2421原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

Wang's Blog

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

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

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

打赏作者

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

抵扣说明:

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

余额充值